[英]What if memory is not allocated to '\0' in char array and char pointer
The following two programs are almost similar. 以下两个程序几乎相似。 In the two programs, memory is not allocated for null(
'\\0'
) character. 在这两个程序中,未为null(
'\\0'
)字符分配内存。
Ex A: 例A:
void main()
{
char *ptr;
ptr = (char *)malloc(2);
strcpy(ptr, "ls");
printf("%s\n",ptr);
system(ptr);
free(ptr);
}
Ex B: 前B:
void main()
{
char ptr[2] = "ls";
system(ptr);
}
1.The first program(Ex. A) is working But i have seen error only with valgrind tool. 1.第一个程序(示例A)正在工作,但是我只看到valgrind工具出错。
output 输出
[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.But the second one is not working 2.但是第二个不起作用
Ex B 前乙
[root@localhost Cprgm]# ./a.out
sh: $'ls%\211\376\177': command not found
Why this happens? 为什么会这样?
TL;DR both the codes cause undefined behavior . TL; DR这两个代码都导致未定义的行为 。
In first case 在第一种情况下
ptr = (char *)malloc(2); strcpy(ptr, "ls");
you're off-by-one, as mentioned in C11
, chapter §7.24.2.3, 就像
C11
第7.24.2.3章中提到的,
The
strcpy
function copies the string pointed to bys2
(including the terminating null character) into the array pointed to bys1
.strcpy
函数将s2
指向的字符串(包括终止空字符)复制到s1
指向的数组中。
So, the size of s1
should at least be strlen(s2)+ 1
. 因此,
s1
的大小至少应为strlen(s2)+ 1
。
In second case 在第二种情况下
char ptr[2] = "ls";
ptr
does not have a null-terminator which in essence, causes out of bound access which again causes UB. ptr
没有空终止符,从本质上讲,它会导致超出范围的访问,从而再次导致UB。
Related, quoting the POSIX manual , 相关,引用POSIX手册 ,
[...] If
command
is not a null pointer, thesystem()
function shall pass the string pointed to bycommand
to that command processor to be executed in an implementation-defined manner;[...]如果
command
不是空指针,则system()
函数必须将command
指向的字符串传递给该命令处理器,以便以实现定义的方式执行; [...][...]
A char
array, without a null-terminator in place, is not considered a string . 没有放置空终止符的
char
数组不视为string 。
Having said that, there are a few sggestions, 话虽如此,但有一些建议,
void main()
should at least be int main(void)
to conform to the standard. void main()
至少应为int main(void)
以符合标准。 malloc()
and family in C
. C
中malloc()
和family的返回值的讨论。 . The array that you used in Ex B is only of length 2. whenever you store a string in a array "ls"
automatically a null character is added with is '\\0' so "ls" will become ls \\0
when it is stored in memory. 在示例B中使用的数组只有长度2。每当将字符串存储在数组
"ls"
系统会自动向其添加一个空字符'\\ 0',因此存储时“ ls”将变为ls \\0
在记忆中。 Most of the algorithm are based on this NULL character to find the length of string of value of string. 大多数算法都是基于此NULL字符来查找string的值的字符串长度。
So just declare your array of length 3 and you will be good to go. 因此,只需声明长度为3的数组,就可以了。
Thanks. 谢谢。
In the first case: 在第一种情况下:
ptr = (char *)malloc(2);
memory is allocated for two bytes but strcpy stored 3 bytes at this location. 内存分配了两个字节,但strcpy在此位置存储了3个字节。 So it is basically a memory corruption case but still "ls" command with \\0 at the end is stored at the location which makes system command to work.
因此,这基本上是一个内存损坏的情况,但是仍然以使系统命令起作用的位置存储以\\ 0结尾的“ ls”命令。
In the second case: 在第二种情况下:
char ptr[2] = "ls";
This assignment itself is wrong and is not supposed to work. 此分配本身是错误的,不应起作用。 Behaviour is undefined.
行为是不确定的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.