c - 不明白为什么我有这些错误:大小为 1 的无效读取和 Syscall param unlink(pathname) 指向无法寻址的字节
c - can't understand why I have these errors: Invalid read of size 1 and Syscall param unlink(pathname) points to unaddressable byte(s)
我正在做一个练习,除其他外,我必须从 txt 文件中读取配置信息,并使用它们来设置服务器。我的代码似乎工作正常,服务器正确启动并且各种缓冲区包含从文件中获取的信息,但是用 valgrind 启动我的程序 returns 这些错误,我不明白我错了什么。
这是主要的
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <config.h>
char* UNIXPATH1=NULL;
void cleanup(){
if(UNIXPATH1!=NULL)
unlink(UNIXPATH1);
}
int main(int argc, char *argv[]) {
FILE *fileconf=fopen("./try/in.txt","r");
if(fileconf==NULL){
fprintf(stderr, "File error\n");
return -1;
}
set_conf(fileconf);
UNIXPATH1=malloc(strlen(returnUnixpath())*sizeof(char));
strncpy(UNIXPATH1,returnUnixpath(),strlen(returnUnixpath()));
cleanup();
atexit(cleanup);
FILE *fileout=fopen(UNIXPATH1,"w");
if(fileout==NULL){
fprintf(stderr, "File error\n");
return -1;
}
fputs("hello",fileout);
fclose(fileout);
free(UNIXPATH1);
return 0;
}
这是config.h
#include <errno.h>
#include <stdlib.h>
#define MEM_ALL(r,c,msg) \
if(!(r=c)) {perror(msg); fprintf(stderr, "ERROR: Out of memory\n"); exit(errno); }
typedef int make_iso_compilers_happy;
char* UNIXPATH;
char* returnUnixpath(){
return UNIXPATH;
}
void set_conf(FILE *file){
char buffer[4096];
char* token1;
char* saveptr1;
char *array[3];
int i;
for(i=0;i<3;i++){
MEM_ALL(array[i],malloc(1*sizeof(char)),"malloc array[i]");
}
i=0;
char* tmp=malloc(sizeof(char));
while(fgets(buffer,4096,file)!=NULL){
if(buffer[0]!='#' && buffer[0]!='\n' && buffer[0]!=' '){
buffer[strlen(buffer)-1]='[=11=]';
token1=strtok_r(buffer," ",&saveptr1);
printf("s: %ld",strlen(token1));
tmp=realloc(tmp,(strlen(token1))*sizeof(char));
strncpy(tmp,token1,(strlen(token1)));
for(i=0;i<3;i++){
MEM_ALL(array[i],realloc(array[i],(strlen(token1)+1)*sizeof(char)),"realloc array[i]");
strncpy(array[i],token1,(strlen(token1)+1));
array[i][strlen(token1)]='[=11=]';
if(i!=2)
token1=strtok_r(NULL," ",&saveptr1);
}
if(strncmp("UnixPath",tmp,8)==0){
MEM_ALL(UNIXPATH,malloc(strlen(array[2])*sizeof(char)),"malloc unixpath");
strncpy(UNIXPATH,array[2],strlen(array[2]));
}
}
}
free(tmp);
for(i=0;i<3;i++){
free(array[i]);
}
fclose(file);
}
这是 in.txt 文件
UnixPath = ./try/o.txt
这是 valgrind 输出
==5897== Invalid read of size 1
==5897== at 0x4C32D04: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x10905C: main (main.c:26)
==5897== Address 0x522e9bb is 0 bytes after a block of size 11 alloc'd
==5897== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x108EB7: set_conf (config.h:44)
==5897== by 0x10904A: main (main.c:25)
==5897==
==5897== Invalid read of size 1
==5897== at 0x4C32D04: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x10907D: main (main.c:27)
==5897== Address 0x522e9bb is 0 bytes after a block of size 11 alloc'd
==5897== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x108EB7: set_conf (config.h:44)
==5897== by 0x10904A: main (main.c:25)
==5897==
==5897== Syscall param unlink(pathname) points to unaddressable byte(s)
==5897== at 0x4F4DD47: unlink (syscall-template.S:78)
==5897== by 0x108FE3: cleanup (main.c:14)
==5897== by 0x1090AC: main (main.c:29)
==5897== Address 0x522ea0b is 0 bytes after a block of size 11 alloc'd
==5897== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x109064: main (main.c:26)
==5897==
==5897== Syscall param openat(filename) points to unaddressable byte(s)
==5897== at 0x4F4BC8E: open (open64.c:47)
==5897== by 0x4EC8589: _IO_file_open (fileops.c:189)
==5897== by 0x4EC8589: _IO_file_fopen@@GLIBC_2.2.5 (fileops.c:281)
==5897== by 0x4EBAEA9: __fopen_internal (iofopen.c:78)
==5897== by 0x4EBAEA9: fopen@@GLIBC_2.2.5 (iofopen.c:89)
==5897== by 0x1090CE: main (main.c:32)
==5897== Address 0x522ea0b is 0 bytes after a block of size 11 alloc'd
==5897== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x109064: main (main.c:26)
==5897==
==5897== Syscall param unlink(pathname) points to unaddressable byte(s)
==5897== at 0x4F4DD47: unlink (syscall-template.S:78)
==5897== by 0x108FE3: cleanup (main.c:14)
==5897== by 0x4E7F040: __run_exit_handlers (exit.c:108)
==5897== by 0x4E7F139: exit (exit.c:139)
==5897== by 0x4E5DB9D: (below main) (libc-start.c:344)
==5897== Address 0x522ea00 is 0 bytes inside a block of size 11 free'd
==5897== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x109138: main (main.c:40)
==5897== Block was alloc'd at
==5897== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x109064: main (main.c:26)
==5897==
s: 8==5897==
==5897== HEAP SUMMARY:
==5897== in use at exit: 11 bytes in 1 blocks
==5897== total heap usage: 15 allocs, 14 frees, 10,377 bytes allocated
==5897==
==5897== LEAK SUMMARY:
==5897== definitely lost: 0 bytes in 0 blocks
==5897== indirectly lost: 0 bytes in 0 blocks
==5897== possibly lost: 0 bytes in 0 blocks
==5897== still reachable: 11 bytes in 1 blocks
==5897== suppressed: 0 bytes in 0 blocks
==5897== Rerun with --leak-check=full to see details of leaked memory
使用strncpy替换所有表格 like
UNIXPATH1=malloc(strlen(returnUnixpath())*sizeof(char));
strncpy(UNIXPATH1,returnUnixpath(),strlen(returnUnixpath()));
通过使用 strdup
UNIXPATH1=strdup(returnUnixpath());
如您所见,这非常实用,并且还解决了您的案例中缺少最后一个字符的问题。当然去掉array[i][strlen(token1)]='[=14=]';
现在没用了
替换如下形式:
tmp=realloc(tmp,(strlen(token1))*sizeof(char));
strncpy(tmp,token1,(strlen(token1)));
来自
tmp=realloc(tmp, strlen(token1) + 1);
strcpy(tmp,token1);
因为 free(UNIXPATH1);
之后的 atexit(cleanup);
你需要在 main 中执行 UNIXPATH1 = NULL;
else cleanup 在 main 执行结束时访问释放的字符串。
其他备注:
- 根据定义
sizeof(char)
是 1
- 将代码放在一个header文件中很奇怪,如果你在多个文件中剪切代码使用多个源文件
- 当您
#include
您的 header 之一使用 "file.h"
而不是 <file.h>
更改后 valgrind 下的执行不会发出无效访问信号
我正在做一个练习,除其他外,我必须从 txt 文件中读取配置信息,并使用它们来设置服务器。我的代码似乎工作正常,服务器正确启动并且各种缓冲区包含从文件中获取的信息,但是用 valgrind 启动我的程序 returns 这些错误,我不明白我错了什么。
这是主要的
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <config.h>
char* UNIXPATH1=NULL;
void cleanup(){
if(UNIXPATH1!=NULL)
unlink(UNIXPATH1);
}
int main(int argc, char *argv[]) {
FILE *fileconf=fopen("./try/in.txt","r");
if(fileconf==NULL){
fprintf(stderr, "File error\n");
return -1;
}
set_conf(fileconf);
UNIXPATH1=malloc(strlen(returnUnixpath())*sizeof(char));
strncpy(UNIXPATH1,returnUnixpath(),strlen(returnUnixpath()));
cleanup();
atexit(cleanup);
FILE *fileout=fopen(UNIXPATH1,"w");
if(fileout==NULL){
fprintf(stderr, "File error\n");
return -1;
}
fputs("hello",fileout);
fclose(fileout);
free(UNIXPATH1);
return 0;
}
这是config.h
#include <errno.h>
#include <stdlib.h>
#define MEM_ALL(r,c,msg) \
if(!(r=c)) {perror(msg); fprintf(stderr, "ERROR: Out of memory\n"); exit(errno); }
typedef int make_iso_compilers_happy;
char* UNIXPATH;
char* returnUnixpath(){
return UNIXPATH;
}
void set_conf(FILE *file){
char buffer[4096];
char* token1;
char* saveptr1;
char *array[3];
int i;
for(i=0;i<3;i++){
MEM_ALL(array[i],malloc(1*sizeof(char)),"malloc array[i]");
}
i=0;
char* tmp=malloc(sizeof(char));
while(fgets(buffer,4096,file)!=NULL){
if(buffer[0]!='#' && buffer[0]!='\n' && buffer[0]!=' '){
buffer[strlen(buffer)-1]='[=11=]';
token1=strtok_r(buffer," ",&saveptr1);
printf("s: %ld",strlen(token1));
tmp=realloc(tmp,(strlen(token1))*sizeof(char));
strncpy(tmp,token1,(strlen(token1)));
for(i=0;i<3;i++){
MEM_ALL(array[i],realloc(array[i],(strlen(token1)+1)*sizeof(char)),"realloc array[i]");
strncpy(array[i],token1,(strlen(token1)+1));
array[i][strlen(token1)]='[=11=]';
if(i!=2)
token1=strtok_r(NULL," ",&saveptr1);
}
if(strncmp("UnixPath",tmp,8)==0){
MEM_ALL(UNIXPATH,malloc(strlen(array[2])*sizeof(char)),"malloc unixpath");
strncpy(UNIXPATH,array[2],strlen(array[2]));
}
}
}
free(tmp);
for(i=0;i<3;i++){
free(array[i]);
}
fclose(file);
}
这是 in.txt 文件
UnixPath = ./try/o.txt
这是 valgrind 输出
==5897== Invalid read of size 1
==5897== at 0x4C32D04: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x10905C: main (main.c:26)
==5897== Address 0x522e9bb is 0 bytes after a block of size 11 alloc'd
==5897== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x108EB7: set_conf (config.h:44)
==5897== by 0x10904A: main (main.c:25)
==5897==
==5897== Invalid read of size 1
==5897== at 0x4C32D04: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x10907D: main (main.c:27)
==5897== Address 0x522e9bb is 0 bytes after a block of size 11 alloc'd
==5897== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x108EB7: set_conf (config.h:44)
==5897== by 0x10904A: main (main.c:25)
==5897==
==5897== Syscall param unlink(pathname) points to unaddressable byte(s)
==5897== at 0x4F4DD47: unlink (syscall-template.S:78)
==5897== by 0x108FE3: cleanup (main.c:14)
==5897== by 0x1090AC: main (main.c:29)
==5897== Address 0x522ea0b is 0 bytes after a block of size 11 alloc'd
==5897== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x109064: main (main.c:26)
==5897==
==5897== Syscall param openat(filename) points to unaddressable byte(s)
==5897== at 0x4F4BC8E: open (open64.c:47)
==5897== by 0x4EC8589: _IO_file_open (fileops.c:189)
==5897== by 0x4EC8589: _IO_file_fopen@@GLIBC_2.2.5 (fileops.c:281)
==5897== by 0x4EBAEA9: __fopen_internal (iofopen.c:78)
==5897== by 0x4EBAEA9: fopen@@GLIBC_2.2.5 (iofopen.c:89)
==5897== by 0x1090CE: main (main.c:32)
==5897== Address 0x522ea0b is 0 bytes after a block of size 11 alloc'd
==5897== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x109064: main (main.c:26)
==5897==
==5897== Syscall param unlink(pathname) points to unaddressable byte(s)
==5897== at 0x4F4DD47: unlink (syscall-template.S:78)
==5897== by 0x108FE3: cleanup (main.c:14)
==5897== by 0x4E7F040: __run_exit_handlers (exit.c:108)
==5897== by 0x4E7F139: exit (exit.c:139)
==5897== by 0x4E5DB9D: (below main) (libc-start.c:344)
==5897== Address 0x522ea00 is 0 bytes inside a block of size 11 free'd
==5897== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x109138: main (main.c:40)
==5897== Block was alloc'd at
==5897== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5897== by 0x109064: main (main.c:26)
==5897==
s: 8==5897==
==5897== HEAP SUMMARY:
==5897== in use at exit: 11 bytes in 1 blocks
==5897== total heap usage: 15 allocs, 14 frees, 10,377 bytes allocated
==5897==
==5897== LEAK SUMMARY:
==5897== definitely lost: 0 bytes in 0 blocks
==5897== indirectly lost: 0 bytes in 0 blocks
==5897== possibly lost: 0 bytes in 0 blocks
==5897== still reachable: 11 bytes in 1 blocks
==5897== suppressed: 0 bytes in 0 blocks
==5897== Rerun with --leak-check=full to see details of leaked memory
使用strncpy替换所有表格 like
UNIXPATH1=malloc(strlen(returnUnixpath())*sizeof(char));
strncpy(UNIXPATH1,returnUnixpath(),strlen(returnUnixpath()));
通过使用 strdup
UNIXPATH1=strdup(returnUnixpath());
如您所见,这非常实用,并且还解决了您的案例中缺少最后一个字符的问题。当然去掉array[i][strlen(token1)]='[=14=]';
现在没用了
替换如下形式:
tmp=realloc(tmp,(strlen(token1))*sizeof(char));
strncpy(tmp,token1,(strlen(token1)));
来自
tmp=realloc(tmp, strlen(token1) + 1);
strcpy(tmp,token1);
因为 free(UNIXPATH1);
之后的 atexit(cleanup);
你需要在 main 中执行 UNIXPATH1 = NULL;
else cleanup 在 main 执行结束时访问释放的字符串。
其他备注:
- 根据定义
sizeof(char)
是 1 - 将代码放在一个header文件中很奇怪,如果你在多个文件中剪切代码使用多个源文件
- 当您
#include
您的 header 之一使用"file.h"
而不是<file.h>
更改后 valgrind 下的执行不会发出无效访问信号