这个malloc应该不起作用

时间:2014-02-04 21:14:34

标签: c malloc

这是我的代码。

 int     main()
  {
  char *s;
  int i = 0;

  printf("%lu \n", sizeof(s));

  s = malloc(sizeof(char) * 2);

  printf("%lu \n", sizeof(s));
  /*Why is this working?*/
  while (i <= 5)
    {
      s[i] = 'l';
      i++;
    }
  printf("%s \n", s);

  printf("%lu \n", sizeof(char));

  printf("%lu \n", sizeof(s[0]));
  }

在我看来,这应该是段错误,因为我试图写的比我分配的多。为什么这有效?

5 个答案:

答案 0 :(得分:6)

  

在我看来,这应该是段错误,因为我试图写的比我分配的多。为什么这有效?

这不是“有效”;您的代码调用未定义的行为。 “未定义的行为”并不意味着“您的代码会出现段错误”。这将是定义的行为。 UB意味着任何事情都会发生。

在这种情况下,你正在踩踏你不拥有的记忆。这有时会出现段错误,但不要指望它。 C没有“段错误”的概念,它来自你的操作系统。

答案 1 :(得分:3)

Segfault是来自操作系统的信号,告诉您访问特定的内存区域不属于您的业务。恰好,您正在访问的内容不会触发操作系统内存管理单元的警报。有很多方法可以利用它(覆盖函数调用,通过覆盖堆栈值来攻击二进制文件等)。

也可能是您的malloc不分配这2个字节和2个字节。 Malloc调用分配虚拟内存页的系统调用(可能超过2个字节)。系统调用(分别用于Linux和Windows的sbrkVirtualAlloc)告诉操作系统将这些页面映射到您需要的页面,然后保护它们以便其他人(阅读:另一个进程/应用程序)意外地进行操作在你的内存区域(因为在这种情况下操作系统会点击 一个人的头部有一个段错误。)

还有其他人提到的未定义行为。

答案 2 :(得分:2)

插图 (并完全同意)@Ed S的回答,试试这个代码示例,添加一些额外的补充变量声明完全相同,并在char *s之后立即进行malloc。

虽然没有保证 变量按顺序存储在内存中,但以这种方式创建它们很有可能。 如果是这样char *t现在将拥有char *s将侵占的空间,并且获得seg错误:

int     main()
{
    char *s;
    char *t;//addition
    int i = 0;

    printf("%lu \n", sizeof(s));

    s = malloc(sizeof(char) * 2);
    t = malloc(sizeof(char) * 2);//addition

    printf("%lu \n", sizeof(s));
    /*Why is this working?*/
    while (i <= 5)
    {
      s[i] = 'l';
      i++;
    }
    printf("%s \n", s);

    printf("%lu \n", sizeof(char));

    printf("%lu \n", sizeof(s[0]));
}

注意: 在我使用的环境中,(Windows 7,NI运行时,调试等)我得到了一个seg-fault,这有点支持其他答案中未定义的行为断言。

答案 3 :(得分:1)

它看起来像这样:malloc分配比你指定的更多的字节..

当你使用malloc(sizeof(s)* 2)时; // 8 然后虽然(i <= 36)是好的,但是虽然(i <= 37)已经没有..

当你使用例如malloc(sizeof(s)* 4)时; // 16 然后虽然(i <= 7572)没问题,但是(i <= 7573)已经没有了..

(我在code :: blocks中测试过)

丹尼斯·里奇已经死了太糟糕了,为什么会这样,这仍然是个大谜 但是,只是不要太担心它只是分配总是足够的 你需要和null终止字符串

答案 4 :(得分:0)

正如其他人所说,它的命中或错过代码是否会导致生产中的运行时错误,因为边界检查没有内置到C ++中(与Java或C#语言不同)。代码将在内存检查器下导致错误。

你可能知道Valgrind,所以这是一个留给读者的练习。 Clang的Address Sanitizer(我添加了一个printf("malloc: %p \n", s);)下面也是一样的:

$ ./t.exe | /usr/local/bin/asan_symbolize.py 
malloc: 0x60200000b3b0 
=================================================================
==98557==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000b3b2 at pc 0x1065c4b5b bp 0x7fff5963b810 sp 0x7fff5963b808
WRITE of size 1 at 0x60200000b3b2 thread T0
    #0 0x1065c4b5a (/Users/jwalton/./t.exe+0x100000b5a)
    #1 0x7fff870e27e0 (/usr/lib/system/libdyld.dylib+0x27e0)
    #2 0x0
0x60200000b3b2 is located 0 bytes to the right of 2-byte region [0x60200000b3b0,0x60200000b3b2)
allocated by thread T0 here:
    #0 0x1065d8cd5 (/usr/local/lib/clang/3.3/lib/darwin//libclang_rt.asan_osx_dynamic.dylib+0xfcd5)
    #1 0x1065c4971 (/Users/jwalton/./t.exe+0x100000971)
    #2 0x7fff870e27e0 (/usr/lib/system/libdyld.dylib+0x27e0)
    #3 0x0
Shadow bytes around the buggy address:
  0x1c0400001620: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c0400001630: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c0400001640: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c0400001650: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c0400001660: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x1c0400001670: fa fa fa fa fa fa[02]fa fa fa 00 00 fa fa fd fa
  0x1c0400001680: fa fa fd fa fa fa 00 00 fa fa fd fa fa fa fd fa
  0x1c0400001690: fa fa 00 00 fa fa 00 00 fa fa fd fa fa fa fd fa
  0x1c04000016a0: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
  0x1c04000016b0: fa fa 00 00 fa fa fd fa fa fa fd fa fa fa 00 00
  0x1c04000016c0: fa fa 00 00 fa fa fd fa fa fa fd fa fa fa 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:     fa
  Heap right redzone:    fb
  Freed heap region:     fd
  Stack left redzone:    f1
  Stack mid redzone:     f2
  Stack right redzone:   f3
  Stack partial redzone: f4
  Stack after return:    f5
  Stack use after scope: f8
  Global redzone:        f9
  Global init order:     f6
  Poisoned by user:      f7
  ASan internal:         fe
==98557==ABORTING