none
在C++/CLI中有个疑问 RRS feed

  • 问题

  • 在之前的“在C++/CLI中,如何获得C++中指针的值?”这个问题中,按照答复把Native C++ cpp 文件中sour=&s改成*sour=s后,程序执行没有问题。现在有个疑问就是,在C++/CLI cpp这个文件原本的代码是:

    C++/CLI cpp file:

    #include "stdafx.h"
    #include "CPlusPlus.h"
    #include "SubFunction.h"
    int SubFunction::Test::StrTest(int d)
    {
        int y;
        int dd = strcpyTest(d, &y);
        xxx = y;
        return dd;
    }

    改成:

    #include "stdafx.h"
    #include "CPlusPlus.h"
    #include "SubFunction.h"
    int SubFunction::Test::StrTest(int d)
    {
        int *y;
        int dd = strcpyTest(d, y);
        xxx = *y;
        return dd;
    }
    运行时就会报System.AccessViolationException:“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”
    这是为什么呢?C++新手学习中,求指点,谢谢!


    努力~


    • 已编辑 zjyh16 2018年10月7日 2:28
    2018年10月7日 2:27

答案

  • 你好,

    感谢在微软论坛发帖。

    >>运行时就会报System.AccessViolationException:"尝试读取或写入受保护的内存,这通常指示其他内存已经损坏。"

    测试了一下,改成 int *y = new int(); 就不会报错了,C++/CLI 内存分三种:栈内存、本机堆内存和托管内存。栈内存中可以包含本机对象和托管对象,退出所在范围其生命周期无差别结束。堆内存是Native C++的动态内存,可以通过new或者malloc关键字动态分配,使用完后由程序员手动释放,托管内存是托管对象的动态内存,由gcnew关键字动态分配。不再使用的托管内存对象有公共运行时垃圾回收器回收,不用程序员处理。

    代码:

    Test.h

    #ifndef __TEST_H__
    #define __TEST_H__
    
        int strcpyTest(int dest, int *sour);
    
    #endif 

    Test.cpp

    #include <iostream>
    #include "Test.h"
    
    
    int strcpyTest(int dest, int *sour)
    {
        int s = dest + 10;
        std::cout << "s" << s << std::endl;
        std::cout << "&s" << &s << std::endl;
        if(NULL != sour) 
            *sour = s;
        int x = *sour + 20;
        std::cout << "sour" << sour << std::endl;
        std::cout << "*sour" << *sour << std::endl;
        return x;
    }

    SubFunction.h

    #pragma once
    using namespace System;
    using namespace System::Runtime::InteropServices;
    namespace SubFunction {
        public ref class Test
        {
        public:
            int StrTest(int d);
            int sub;
        };
    }

    SubFunction.cpp

    #include "Test.h" #include "SubFunction.h" int SubFunction::Test::StrTest(int d) { int *y = new int(); int dd = strcpyTest(d, y); sub = *y;

    delete y;

    return dd; }

    manage.cs

    using System;
    using SubFunction;
    using System.Windows.Forms;
    class Manage
    {
        public static void Main()
        {
            int a = 15;
            int b = 20;
            Test ts = new Test();
            int c = ts.StrTest(a);
            int d = ts.sub;
    
            MessageBox.Show(c.ToString());
            MessageBox.Show(d.ToString());
    
            Console.WriteLine("Hello World!");
            Console.ReadKey();
        }
    }

    编译过程:

    第一步: cl.exe /Zi /MD /c Test.cpp
    第二步: cl.exe /Zi /clr /c SubFunction.cpp
    第三步: csc /target:module /addmodule:SubFunction.obj Manage.cs
    第四步: link SubFunction.obj Test.obj Manage.netmodule /entry:Manage.Main /out:manage.exe /subsystem:console /ltcg

    运行结果:


    Best Wishes,

    Jack Zhang


    MSDN Community Support Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • 已标记为答案 zjyh16 2018年10月8日 14:18
    2018年10月8日 7:51
    版主

全部回复

  • 你好,

    感谢在微软论坛发帖。

    >>运行时就会报System.AccessViolationException:"尝试读取或写入受保护的内存,这通常指示其他内存已经损坏。"

    测试了一下,改成 int *y = new int(); 就不会报错了,C++/CLI 内存分三种:栈内存、本机堆内存和托管内存。栈内存中可以包含本机对象和托管对象,退出所在范围其生命周期无差别结束。堆内存是Native C++的动态内存,可以通过new或者malloc关键字动态分配,使用完后由程序员手动释放,托管内存是托管对象的动态内存,由gcnew关键字动态分配。不再使用的托管内存对象有公共运行时垃圾回收器回收,不用程序员处理。

    代码:

    Test.h

    #ifndef __TEST_H__
    #define __TEST_H__
    
        int strcpyTest(int dest, int *sour);
    
    #endif 

    Test.cpp

    #include <iostream>
    #include "Test.h"
    
    
    int strcpyTest(int dest, int *sour)
    {
        int s = dest + 10;
        std::cout << "s" << s << std::endl;
        std::cout << "&s" << &s << std::endl;
        if(NULL != sour) 
            *sour = s;
        int x = *sour + 20;
        std::cout << "sour" << sour << std::endl;
        std::cout << "*sour" << *sour << std::endl;
        return x;
    }

    SubFunction.h

    #pragma once
    using namespace System;
    using namespace System::Runtime::InteropServices;
    namespace SubFunction {
        public ref class Test
        {
        public:
            int StrTest(int d);
            int sub;
        };
    }

    SubFunction.cpp

    #include "Test.h" #include "SubFunction.h" int SubFunction::Test::StrTest(int d) { int *y = new int(); int dd = strcpyTest(d, y); sub = *y;

    delete y;

    return dd; }

    manage.cs

    using System;
    using SubFunction;
    using System.Windows.Forms;
    class Manage
    {
        public static void Main()
        {
            int a = 15;
            int b = 20;
            Test ts = new Test();
            int c = ts.StrTest(a);
            int d = ts.sub;
    
            MessageBox.Show(c.ToString());
            MessageBox.Show(d.ToString());
    
            Console.WriteLine("Hello World!");
            Console.ReadKey();
        }
    }

    编译过程:

    第一步: cl.exe /Zi /MD /c Test.cpp
    第二步: cl.exe /Zi /clr /c SubFunction.cpp
    第三步: csc /target:module /addmodule:SubFunction.obj Manage.cs
    第四步: link SubFunction.obj Test.obj Manage.netmodule /entry:Manage.Main /out:manage.exe /subsystem:console /ltcg

    运行结果:


    Best Wishes,

    Jack Zhang


    MSDN Community Support Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • 已标记为答案 zjyh16 2018年10月8日 14:18
    2018年10月8日 7:51
    版主
  • 谢谢Jack Zhang-MSFT!也就是说先要分配一个内存,如果不分配没有就没法写入内存的意思吧。也正好刚刚看到的一句话,“使用未初始化的局部指针变量是件很危险的事,所以,在使用局部指针变量时,一定要及时将其初始化。”应该是这个意思吧。学习了。

    努力~

    2018年10月8日 14:23