c - не могу понять, почему у меня есть такие ошибки: неверное чтение размера 1 и unlink (pathname) параметра Syscall указывает на неадресуемые байты - PullRequest
0 голосов
/ 05 февраля 2019

Я выполняю упражнение, в котором, помимо прочего, мне нужно прочитать информацию о конфигурации из txt-файла и использовать их для настройки сервера.Мой код, кажется, работает, сервер запускается правильно, и различные буферы содержат информацию, взятую из файла, но запуск моей программы с valgrind возвращает эти ошибки, я не могу понять, в чем я не прав.

этоосновной

#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]='\0';
            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)]='\0';  
                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

1 Ответ

0 голосов
/ 05 февраля 2019

Замените все формы, используя strncpy как

UNIXPATH1=malloc(strlen(returnUnixpath())*sizeof(char));
strncpy(UNIXPATH1,returnUnixpath(),strlen(returnUnixpath()));

, используя strdup

UNIXPATH1=strdup(returnUnixpath());

, как вы можете видеть этоочень практично, и это также решает проблему отсутствия последнего символа в вашем случае.Конечно, удалить array[i][strlen(token1)]='\0'; теперь бесполезно.

Заменить формы как:

tmp=realloc(tmp,(strlen(token1))*sizeof(char));
strncpy(tmp,token1,(strlen(token1)));

на

tmp=realloc(tmp, strlen(token1) + 1);
strcpy(tmp,token1);

Из-за atexit(cleanup); после free(UNIXPATH1); вам нужноUNIXPATH1 = NULL; в main else cleanup доступ к освобожденной строке в конце выполнения main .

Другие замечания:

  • по определению sizeof(char) равно 1
  • странно помещать код в заголовочный файл, если вы вырезаете код в нескольких файлах, используйте несколько исходных файлов
  • , когда вы#include один из ваших заголовков использует "file.h" вместо <file.h>

После изменений выполнение в valgrind не сигнализирует о недопустимых доступах

...