精华内容
下载资源
问答
  • 读书笔记:C++中利用智能指针和值型类防止内存非法访问 读书笔记:C++中利用智能指针和值型类防止内存非法访问2013-03-10 18:18 by DVwei, 138 阅读, 0 评论, 收藏, 编辑 在程序当中,经常会用到一些共享...

     读书笔记:C++中利用智能指针和值型类防止内存非法访问
    2013-03-10 18:18 by DVwei, 138 阅读, 0 评论, 收藏, 编辑

    在程序当中,经常会用到一些共享对象。一个具有指针成员的类,如果发生复制行为,一个指针复制到另一个指针时,两个指针就指向同一个对象。此时就可以使用任一指针改变这个共享的对象。那么,如果一个指针删除了这个共享对象,那么另一指针就成了悬垂指针,如果再对此对象进行操作时,就会发生内存访问错误。而C++中无法判断一个指针所指向的内存是否有效,这是非常危险的。

    看下面一个例子:
    复制代码

    class MyClass
    {
        public:
            MyClass(int *p,int i): ptr(p),value(i) { }
            ~MyClass() { delete ptr; }
            int get_share_value() { return *ptr; }
            int get_value() { return value; }
            void set_share_value(int i) { *ptr = i; }
            void set_value(int i) { value = i; }
        private:
            int *ptr;
            int value;
    };

    int main()
    {int *p  = new int(10);
        MyClass test(p,20);
        MyClass test2(test);
        test.get_share_value();//return 10
        test2.get_share_value();//return 10
        
        test2.set_share_value(110);
        test.get_share_value();//return 110
        
        test.set_share_value(120);
        test2.get_share_value();//return 120
        
        return 0;
    }

    复制代码

    可以看到,使用任一指针都能改变共享的对象。而且运行这段代码就能发现程序结束的时候发生错误。这是因为,程序结束时,编译器会调用test和test2的析构函数,这样就发生了两次delete ptr,第一次delete释放掉val,第二次delete时,指针所指向的内存已经无效,所以就会发生内存访问错误。

    为了避免出现重复delete同一对象的情况,可以定义智能指针来管理共享的对象。所谓智能指针,其实是引入一个使用计数,并建立一个计数类,用来记录目前指向同一对象的指针数目,确保只剩下最后一个指向对象时才删除对象。

    代码如下:
    复制代码

    #include <iostream>

    using namespace std;

    class MyClass;

    class Use_Ptr
    {
        friend class MyClass;
        int *ptr;
        size_t use;
        Use_Ptr(int *p): ptr(p), use(1) { }
        ~Use_Ptr() { delete ptr; }
    };

    class MyClass
    {
        public:
            MyClass(int *p,int i): ptr(new Use_Ptr(p)), value(i) { }

            //发生复制行为时,记录使用次数
            MyClass(const MyClass &mc): ptr(mc.ptr), value(mc.value) { ++ptr->use; }
            ~MyClass() { if(--ptr->use == 0) delete ptr; }//撤销对象前检查使用计数是否为零,若为零,撤销对象

            MyClass& operator=(const MyClass&);
            int get_share_value() { return *ptr->ptr; }
            int get_value() { return value; }
            void set_share_value(int i) { *ptr->ptr = i; }
            void set_value(int i) { value = i; }
        private:
            Use_Ptr *ptr;
            int value;
    };

    MyClass& MyClass::operator=(const MyClass &mc)
    {
        ++mc.ptr->use;//使用use之前先将sm.ptr->use加一,防止对自身赋值
        if(--ptr->use == 0)
          delete ptr;
        ptr = mc.ptr;

        return *this;
    }


    int main()
    {
        int *p = new int(10);

        MyClass test(p,20);
        MyClass copy(test);
        return 0;
    }

    复制代码

    这样就确保了共享的对象在没有指针指向它的时候才被delete掉,也就不会发生内存的非法访问了。

    另一种方法是把类设计成和值类型具有相同的复制行为,即复制类对象的同时复制指针指向的值,而不是只复制指针的值。于是可以把上述MyClass这样定义:
    复制代码

    class MyClass
    {
        public:
            MyClass(int &p,int i): ptr(new int(p)), value(i) { }
            MyClass(const MyClass &mc): ptr(new int(*mc.ptr)), value(mc.value) { }//把值也复制
            ~MyClass() { delete ptr; }//这里可以直接释放

            MyClass& operator=(const MyClass&);
            int get_share_value() { return *ptr; }
            int get_value() { return value; }
            void set_share_value(int i) { *ptr = i; }
            void set_value(int i) { value = i; }

        private:
            int *ptr;
            int value;
    };

    MyClass& MyClass::operator=(const MyClass &mc)
    {
        *ptr = *mc.ptr;
        value = mc.value;

        return *this;
    }

    复制代码

    这样每个指针都指向一个值相同但相互独立的对象,delete后也不会影响到其他的对象。

    这种方法也叫深度复制,在C#中可以通过实现clone接口来完成。

    posted on 2013-03-24 14:15 lexus 阅读(...) 评论(...) 编辑 收藏

    转载于:https://www.cnblogs.com/lexus/archive/2013/03/24/2978537.html

    展开全文
  • 【Linux开发】GCC 4.8及以上支持内存非法访问检查 2015-2-27阅读162 评论0 gcc4.8及以上版本支持地址越界,野指针检查,只需要在编译时使用-fsanitize=address选项即可,当运行程序时如果访问非本程序申请...

    【Linux开发】GCC 4.8及以上支持内存非法访问检查

    2015-2-27阅读162 评论0

    gcc4.8及以上版本支持地址越界,野指针检查,只需要在编译时使用-fsanitize=address选项即可,当运行程序时如果访问非本程序申请的地址就会报错。
    root@localhost:/home/ngos/practice> vi nullpoint.c
          1 #include "stdio.h"
          2 
          3 int main(int argc , char **argv)
          4 {
          5         int *p = NULL;
          6         *p = 10;
          7         printf("%d",*p);
          8 
          9         return 0;
         10 }
    root@localhost:/home/ngos/practice> gcc -g  -fsanitize=address -o nullpoint nullpoint.c 
    root@localhost:/home/ngos/practice> ls
    nullpoint  nullpoint.c
    root@localhost:/home/ngos/practice> ./nullpoint 
    ASAN:SIGSEGV
    =================================================================
    ==3696==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x00000040085a sp 0x7fff603db8b0 bp 0x7fff603db8d0 T0)
        #0 0x400859 in main /home/ngos/practice/nullpoint.c:6
        #1 0x7faa9bd19b5d in __libc_start_main (/lib64/libc.so.6+0x1eb5d)
        #2 0x4006c8 (/home/ngos/practice/nullpoint+0x4006c8)

    AddressSanitizer can not provide additional info.
    SUMMARY: AddressSanitizer: SEGV /home/ngos/practice/nullpoint.c:6 main
    ==3696==ABORTING
    由上面的错误提示信息可以看到第6行存在指针错误。


    另外还有一个-fsanitize=leak东东,可以检测内存泄露的哦~

    程序结束会打印出关于泄露的log


    以上两个选项可以同时开
    ps:使用这个会导致执行变慢一些,影响不是很大,但是还是建议程序测试期使用。

    展开全文
  • 那么,如果一个指针删除了这个共享对象,那么另一指针成了悬垂指针,如果再对此对象进行操作时,会发生内存访问错误。而C++中无法判断一个指针所指向的内存是否有效,这是非常危险的。  看下面一个例子: class...
  • 1、一般都是非法内存操作,例如数组越界,例如申请a[5],却访问到a[5]或者a[6],这也会有很多情况,可能是循环操作时循环变量控制有问题,可能是字符串拷贝时长度发生溢出; 2、指针指向了非法内存,例如定义了一个指针,...

    1、一般都是非法内存操作,例如数组越界,例如申请a[5],却访问到a[5]或者a[6],这也会有很多情况,可能是循环操作时循环变量控制有问题,可能是字符串拷贝时长度发生溢出;
    2、指针指向了非法内存,例如定义了一个指针,但是没有对指针进行初始化,直接就引用,或者引用里面的元素或者函数,或者没有分配内存就进行释放等,另外,申请内存还要检查是否申请成功,如果没有申请成功也会出现这种情况;
    3、如果递归爆栈,也会报这个错误。内存过大时本地不报错,因为我们本地内存很大,但在线编程题每个题都会有内存限制。

    展开全文
  • 网上看了一圈,说什么调整batchsize啥的,设置多卡啥的,根本不起作用,建议使用torch1.2查一下你是不是to(device)漏了,比如我在transformer Encoder时候忘记把Position编码的参数to(device)了,再torch1.2中就会...

    网上看了一圈,说什么调整batchsize啥的,设置多卡啥的,根本不起作用,建议使用torch1.2查一下你是不是to(device)漏了,比如我在transformer Encoder时候忘记把Position编码的参数to(device)了,再torch1.2中就会直接报错,而在torch1.6的版本就会出现上述的错误,死活搞不定!所以可以有个torch1.2的版本搞定了model,再使用torch1.6重新运行,这样不但能使用tensorboard(torch1.2的board不能显示图形),奇怪的错误(torch1.6总会出现奇奇怪怪的错误)也不见了。

    展开全文
  • C_内存非法访问问题

    2013-05-17 10:56:06
    #include <stdio.h> char *func(void) { char *str = "Hello world"; return str; } int main(void) { char *p = NULL; p = func(); return 0;...会存在非法内存访问吗?
  • GCC 4.8及以上支持内存非法访问检查

    千次阅读 2017-07-28 18:47:26
    gcc4.8及以上版本支持地址越界,野指针检查,只需要在编译时使用-fsanitize=address选项即可,当运行程序时如果访问非本程序申请的地址就会报错。 root@localhost:/home/ngos/practice> vi nullpoint.c 1 #...
  • 文中只是谈些Dll的调用问题,只是自己的经验。 开始自己编写的Dll是有VC6...问题就是主程序里传指针给Dll里的Vector指针,传的进去,但是在Dll指针的地址为空,异常在网上说是0X000005地址内容非法访问,最后也是没
  • 一种内存非法访问【C++警示录一】

    千次阅读 2009-12-24 17:25:00
    的时候内存非法访问 这是什么原因?仍未解决,跪求原因     //用到的函数 void DealStrWitht(char *str) {  char *s=str;  char *addstr="/t";  while(*s != ' ' && *s != '/0')  {  s++;  }...
  • rerun with: -v ==27955== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6) Segmentation fault [root@xxx ~/valgrind-3.8.1/bin]# 可以看到, 第6行有内存非法访问, 程序core dump了。...
  • 原因跟之前一样,对象在内存中已经被销毁,或者这个对象压根就没有被创建过。 慢慢的查找p_Screen在哪里被复制以及在哪里被销毁,最有效的方法就是看函数调用栈。 当我把断点设置在p_Screen赋值语句的那一行时,...
  • 三 用Valgrind检测非法访问内存 [root@localhost charpter05]# valgrind ./0508 ==16719== Memcheck, a memory error detector ==16719== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. =...
  • 这几天遇到一个诡异的问题,关于C#调用 C++dll... 调用方法的时候, 都提示_ledHandle 非法访问内存。 然而 把_ledHandle 定义为局部变量的时候,是OK的。 很奇怪,百思不得其解............... ...
  • 访问非法内存 越界等

    2018-08-05 07:41:04
    1:一般都是非法内存操作,例如数组越界,例如申请a[5],却访问到a[5]或者a[6],这也会有很多情况,可能是循环操作时循环变量控制有问题,可能是字符串拷贝时长度发生溢出; 2:指针指向了非法内存,例如申明一个指针,但是...
  • 访问非法内存区和内存泄漏

    千次阅读 2018-08-10 17:16:09
    (Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。 内存泄漏原因通常是new之后没有用delete释放堆上的资源  ...
  • 原理:对内存页面设置PAGE_NOACCESS保护 当程序内访问改页面内数据时产生ACCESS_VIOLATION 产生异常被VEH捕获 VEH处理函数内还原内存页面PAGE_READWRITE属性 然后设置ExceptionInfo->ContextRecord->EFlags |=...
  • #include <stdio.h> int main() { char* str=NULL; scanf("%s",str); printf("%s\n",str); return 0; } 以上编译时是没问题的,运行时显示非法内存访问,不知是什么原因。
  • 一 代码 #include int main(){ int b=1; ...[root@localhost charpter05]# cp /data/coredump/core....发现a变量指向地址是非法地址,也就是因为a没有分配内存导致。 第6行应该修改为:a=&b,这样a就指向b了。
  • 非法内存访问会产生SIGSEGV signal, 测试代码如下: #include #include static void _crash_test(void) {  char* pt_str = "test_string";  *pt_str = 'o'; } int main(int argc, char* argv[]) { ...
  • 1. 字符串 1) strcpy, strcat 2) sscanf 2. 空指针 或 指向非法内存的指针 3. memcpy 4. 访问无效句柄 转载于:https://www.cnblogs.com/lin1270/archive/2012/03/20/2409079.html...
  • 具体可以搜《Linux系统下借助mcheck实现c/c++程序的堆内存异常检查》这篇文章,比较详细。我比较喜欢用其中的b、c两种: b. 在makefile中使用-lmcheck来链接程序。优点:无需在源码中显式调用mcheck,且一定可以
  •  问题描述: 应用程序崩溃,或安装 Visual Studio 2013年或.NET Framework 4.5.1 后,使用 System....EF使用System.Data.SqlClient也会报内存访问非法异常。 异常堆栈4种,仅列一种: .SNIAddProvider(SNI_C

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,292
精华内容 516
关键字:

内存非法访问