当我使用一些C代码时,我遇到了这个奇怪的错误。
我在代码中犯了一个错误,并写到buf
而不是&buf
,但是几乎正常。
...
void* buf;
int ret;
int fd = open("1", O_CREAT | O_RDWR, 0777);
write(fd, "test\n", 5);
lseek(fd, 0, SEEK_SET);
ret = read(fd, buf, 5); // Yes, this should be &buf
printf("Ret: %d Str: %s\n", ret, buf);
---- output ----
Ret: 5 Str: test\n
此代码有效,即使我的读取调用中应该有test\n
,我的标准输出中也会得到&buf
。请注意,将buf
更改为&buf
是可行的。那不是问题。
这是行不通的:
...
void* buf;
void* blah = "a"; // Using char* still did not work
int ret;
int fd = open("1", O_CREAT | O_RDWR, 0777);
write(fd, "test\n", 5);
lseek(fd, 0, SEEK_SET);
ret = read(fd, buf, 5);
printf("Ret: %d Str: %s\n", ret, buf);
---- output ----
Ret: -1 Str: 1�I��^H��H���PTI��`@
文件1
的二进制文件对于两个程序都是相同的。写入1
时没有错误。
第一个代码段为何起作用?
如何添加从未使用过的变量,这不再 工作吗?
为什么首先要写buf
而不写&buf
?
以下是每个二进制文件中的字符串部分:
功能代码:
0000770: 0100 0200 0000 0000 0000 0000 0000 0000 ................
0000780: 3100 7465 7374 0a00 4572 723a 2025 640a 1.test..Err: %d.
0000790: 0a00 5374 723a 2025 730a 0000 011b 033b ..Str: %s......;
00007a0: 3000 0000 0500 0000 34fd ffff 7c00 0000 0.......4...|...
故障代码:
0000770: 0100 0200 0000 0000 0000 0000 0000 0000 ................
0000780: 6100 3100 7465 7374 0a00 4572 723a 2025 a.1.test..Err: %
0000790: 640a 0a00 5374 723a 2025 730a 0000 0000 d...Str: %s.....
00007a0: 011b 033b 3400 0000 0500 0000 30fd ffff ...;4.......0...
谢谢。
答案 0 :(得分:0)
(由于几乎不可能在注释中添加多行代码)
使用-Wall -Wextra
进行编译的警告:
x.c: In function ‘main’:
x.c:15:25: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘void *’ [-Wformat=]
printf("Ret: %d Str: %s\n", ret, buf);
~^
%p
x.c:14:9: warning: ‘buf’ is used uninitialized in this function [-Wuninitialized]
ret = read(fd, buf, 5);
^~~~~~~~~~~~~~~~
通过valgrind运行程序的结果:
==6978== Memcheck, a memory error detector
==6978== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6978== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==6978== Command: ./a.out
==6978==
==6978== Syscall param read(buf) contains uninitialised byte(s)
==6978== at 0x4F4C081: read (read.c:27)
==6978== by 0x1087BF: main (x.c:14)
==6978==
==6978== Syscall param read(buf) points to unaddressable byte(s)
==6978== at 0x4F4C081: read (read.c:27)
==6978== by 0x1087BF: main (x.c:14)
==6978== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==6978==
==6978== Conditional jump or move depends on uninitialised value(s)
==6978== at 0x4E97A41: vfprintf (vfprintf.c:1643)
==6978== by 0x4EA0F25: printf (printf.c:33)
==6978== by 0x1087DC: main (x.c:18)
==6978==
Ret: -1 Str: (null)
==6978==
==6978== HEAP SUMMARY:
==6978== in use at exit: 0 bytes in 0 blocks
==6978== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==6978==
==6978== All heap blocks were freed -- no leaks are possible
==6978==
==6978== For counts of detected and suppressed errors, rerun with: -v
==6978== Use --track-origins=yes to see where uninitialised values come from
==6978== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
您必须使buf
指向您有权使用的有效内存,否则您将获得未定义的行为,任何事情都可能发生。如果幸运的话,它只会使您的程序崩溃,但您不能指望它。