工作程序中多个valgrind“读取大小为n的无效”

时间:2017-11-01 06:14:22

标签: c malloc valgrind

以下是从具有多个线程的文件中检索文本的相关示例(添加的行号依赖于valgrind消息):

001:     #define _POSIX_C_SOURCE 200809L
002: 
003:     #include <stdio.h>
004:     #include <stdlib.h>
005:     #include <pthread.h>
006:     #include <stdint.h>
007:     #include <unistd.h>
008:     #include <string.h>
009: 
010:     typedef struct Ft {
011:         FILE *fp;
012:         int seekpoint;
013:         int seekwidth;
014:     } Ft;
015: 
016:     off_t get_file_length(FILE *file) {
017:         fpos_t position; // fpos_t may be a struct and store multibyte info
018:         off_t length; // off_t is integral type, perhaps long long
019: 
020:         fgetpos(file, &position); // save previous position in file
021: 
022:         fseeko(file, 0, SEEK_END); // seek to end
023:         length = ftello(file); // determine offset of end
024: 
025:         fsetpos(file, &position); // restore position
026: 
027:         return length;
028:     }
029: 
030:     Ft *get_ft(FILE *fp, int seekpoint, int seekwidth) {
031:        Ft *ft = malloc(sizeof(Ft));
032:        if(!ft) return NULL;
033: 
034:        ft->fp = fp;
035:        ft->seekpoint = seekpoint;
036:        ft->seekwidth = seekwidth;
037:        return ft;
038:     }
039: 
040:     void *thread_read(void *arg) {
041:        Ft* fi = (Ft*)arg;
042:        unsigned char *buf = malloc(fi->seekwidth * sizeof(char));
043: 
044:        if (pread(fileno(fi->fp), buf, fi->seekwidth, fi->seekpoint) == -1) {
045:           fprintf(stderr, "error seeking and/or reading at: %d\n", fi->seekpoint);
046:           exit(EXIT_FAILURE);
047:        }
048: 
049:        return buf;
050:     }
051: 
052:     char* concat(const char *s1, const char *s2)
053:     {
054:         const size_t len1 = strlen(s1);
055:         const size_t len2 = strlen(s2);
056:         char *result = malloc(len1+len2+1);//+1 for the null-terminator
057:         //in real code you would check for errors in malloc here
058:         memcpy(result, s1, len1);
059:         memcpy(result+len1, s2, len2+1);//+1 to copy the null-terminator
060:         return result;
061:     }
062: 
063:     int main() {
064:          // load text file and image
065:        char *file_name = "file.txt";
066:        int thread_count = 5;
067: 
068:        FILE *f = fopen(file_name, "r");
069:        if(f == NULL) {
070:          fprintf(stderr, "file %s does not exist\n", file_name);
071:          return EXIT_FAILURE;
072:        }
073:        int text_size = get_file_length(f);
074: 
075:        // Number of characters each thread should read.
076:        int seekwidth = (text_size / thread_count), seekpoint;
077: 
078:        pthread_t threads[thread_count];
079:        for (int i = 0; i < thread_count; i++) {
080:             seekpoint = seekwidth * i;
081:             if(i == thread_count - 1)// last thread might have more work
082:               seekwidth += (text_size % thread_count);
083: 
084:             if (pthread_create(&threads[i], NULL, thread_read, get_ft(f, seekpoint, seekwidth)) != 0) {
085:               fprintf(stderr, "pthread_create failed!\n");
086:               return EXIT_FAILURE;
087:             }
088:        }
089: 
090:        void *retrieve;
091:        char *text = "";
092: 
093:        for(int i = 0; i < thread_count; i++) {
094:           if(pthread_join(threads[i], &retrieve) != 0) {
095:               fprintf(stderr, "pthread_join failed!\n");
096:               return EXIT_FAILURE;
097:           }
098:           text = concat(text, retrieve);
099:        }
100: 
101:        printf("%s\n", text);
102: 
103:        fclose(f);
104:        free(text);
105:        return EXIT_SUCCESS;
106:     }

该程序运行正常,但valgrind向我显示这些错误:

==23883== Invalid read of size 1
==23883==    at 0x4C30F74: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23883==    by 0x400D35: concat (test.c:55)
==23883==    by 0x400F97: main (test.c:98)
==23883==  Address 0x5422b15 is 0 bytes after a block of size 5 alloc'd
==23883==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23883==    by 0x400C91: thread_read (test.c:42)
==23883==    by 0x4E416B9: start_thread (pthread_create.c:333)
==23883==
==23883== Invalid read of size 2
==23883==    at 0x4C3272E: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23883==    by 0x400D8D: concat (test.c:59)
==23883==    by 0x400F97: main (test.c:98)
==23883==  Address 0x5422b14 is 4 bytes inside a block of size 5 alloc'd
==23883==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23883==    by 0x400C91: thread_read (test.c:42)
==23883==    by 0x4E416B9: start_thread (pthread_create.c:333)
==23883==
==23883== Invalid read of size 1
==23883==    at 0x4C32758: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23883==    by 0x400D8D: concat (test.c:59)
==23883==    by 0x400F97: main (test.c:98)
==23883==  Address 0x5422b65 is 0 bytes after a block of size 5 alloc'd
==23883==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23883==    by 0x400C91: thread_read (test.c:42)
==23883==    by 0x4E416B9: start_thread (pthread_create.c:333)

我真的很失望,我不知道为什么会这样。

1 个答案:

答案 0 :(得分:1)

当在<a href="<?php echo site_url('Home/contactUs'); ?>">CLICK ME</a> 函数中构造字符串时,不为空终止符分配空间并在字符串结尾之后写入它。因此,thread_read中的strlen调用将超出分配的内存区域的末尾。