[英]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 。
話雖如此,但有一些建議,
void main()
至少應為int main(void)
以符合標准。 C
中malloc()
和family的返回值的討論。 。 在示例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.