以下是从具有多个线程的文件中检索文本的相关示例(添加的行号依赖于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)
我真的很失望,我不知道为什么会这样。
答案 0 :(得分:1)
当在<a href="<?php echo site_url('Home/contactUs'); ?>">CLICK ME</a>
函数中构造字符串时,不为空终止符分配空间并在字符串结尾之后写入它。因此,thread_read
中的strlen
调用将超出分配的内存区域的末尾。