簡體   English   中英

如果在char數組和char指針中未將內存分配給'\\ 0'怎么辦

[英]What if memory is not allocated to '\0' in char array and char pointer

以下兩個程序幾乎相似。 在這兩個程序中,未為null( '\\0' )字符分配內存。

例A:

void main()
{
        char *ptr;
        ptr = (char *)malloc(2);
        strcpy(ptr, "ls");
        printf("%s\n",ptr);
        system(ptr);
        free(ptr);
}

前B:

void main()
{
        char ptr[2] = "ls"; 
        system(ptr);
}

1.第一個程序(示例A)正在工作,但是我只看到valgrind工具出錯。

輸出

[root@localhost tmp]# valgrind --leak-check=full ./a.out 
==8619== Memcheck, a memory error detector
==8619== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==8619== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==8619== Command: ./a.out
==8619== 
==8619== Invalid write of size 1
==8619==    at 0x400635: main (in /home/gen4linux/Projects/Cprgm/tmp/a.out)
==8619==  Address 0x51f2042 is 0 bytes after a block of size 2 alloc'd
==8619==    at 0x4C29C4F: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==8619==    by 0x400627: main (in /home/gen4linux/Projects/Cprgm/tmp/a.out)
==8619== 
==8619== Invalid read of size 1
==8619==    at 0x4C2CC14: strlen (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==8619==    by 0x4EA4D3B: puts (in /usr/lib64/libc-2.20.so)
==8619==    by 0x400644: main (in /home/gen4linux/Projects/Cprgm/tmp/a.out)
==8619==  Address 0x51f2042 is 0 bytes after a block of size 2 alloc'd
==8619==    at 0x4C29C4F: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==8619==    by 0x400627: main (in /home/gen4linux/Projects/Cprgm/tmp/a.out)
==8619== 
ls
==8620== Syscall param execve(argv[i]) points to unaddressable byte(s)
==8620==    at 0x4EF9537: execve (in /usr/lib64/libc-2.20.so)
==8620==    by 0x4E77D18: do_system (in /usr/lib64/libc-2.20.so)
==8620==    by 0x400650: main (in /home/gen4linux/Projects/Cprgm/tmp/a.out)
==8620==  Address 0x51f2042 is 0 bytes after a block of size 2 alloc'd
==8620==    at 0x4C29C4F: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==8620==    by 0x400627: main (in /home/gen4linux/Projects/Cprgm/tmp/a.out)
==8620== 
a.out  test37.c
==8619== 
==8619== HEAP SUMMARY:
==8619==     in use at exit: 0 bytes in 0 blocks
==8619==   total heap usage: 1 allocs, 1 frees, 2 bytes allocated
==8619== 
==8619== All heap blocks were freed -- no leaks are possible
==8619== 
==8619== For counts of detected and suppressed errors, rerun with: -v
==8619== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

2.但是第二個不起作用

前乙

[root@localhost Cprgm]# ./a.out 
sh: $'ls%\211\376\177': command not found

為什么會這樣?

TL; DR這兩個代碼都導致未定義的行為

  • 在第一種情況下

     ptr = (char *)malloc(2); strcpy(ptr, "ls"); 

    就像C11第7.24.2.3章中提到的,

    strcpy函數將s2指向的字符串(包括終止空字符)復制到s1指向的數組中。

    因此, s1大小至少應為strlen(s2)+ 1

  • 在第二種情況下

     char ptr[2] = "ls"; 

    ptr沒有空終止符,從本質上講,它會導致超出范圍的訪問,從而再次導致UB。

    相關,引用POSIX手冊

    [...]如果command不是空指針,則system()函數必須將command指向的字符串傳遞給該命令處理器,以便以實現定義的方式執行; [...]

    沒有放置空終止符的char數組不視為string


話雖如此,但有一些建議,

在示例B中使用的數組只有長度2。每當將字符串存儲在數組"ls"系統會自動向其添加一個空字符'\\ 0',因此存儲時“ ls”將變為ls \\0在記憶中。 大多數算法都是基於此NULL字符來查找string的值的字符串長度。

因此,只需聲明長度為3的數組,就可以了。

謝謝。

在第一種情況下:

ptr = (char *)malloc(2);

內存分配了兩個字節,但strcpy在此位置存儲了3個字節。 因此,這基本上是一個內存損壞的情況,但是仍然以使系統命令起作用的位置存儲以\\ 0結尾的“ ls”命令。

在第二種情況下:

char ptr[2] = "ls";

此分配本身是錯誤的,不應起作用。 行為是不確定的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM