尝试将字符串复制到结构成员变量时,Valgrind 警告重叠

Valgrind warns of overlap when trying to copy a string into a struct member variable

这是结构的样子以供参考:

struct thread_data {
    struct ringbuf_t *rb;
    char *file_name;
};

我需要获取命令行参数并将其存储在 threads 数组中每个 thread_data 元素的结构成员变量中,如下所示:

for (int index = optind; index < argc; index++) {
        threads[length].rb = rb;
        memmove(&threads[length].file_name, &argv[index], strlen(argv[index]));
        strcpy(threads[length].file_name, argv[index]);
        ++length;
    }

以前使用过 memcpy,当我打印变量时它起作用了。然而,Valgrind 给我的是:

==465645== Source and destination overlap in strcpy(0x1fff000b54, 0x1fff000b54)
==465645==    at 0x4C3C180: strcpy (vg_replace_strmem.c:523)
==465645==    by 0x400F85: main (bytemincer.c:55)

所以我使用了 memmove 并且我仍然得到相同的 Valgrind 结果。有什么解决办法吗?

这就是你想要的结果:

(我在 post 中使用“fn”而不是“file_name”。)

                                      *(argv[0]) @ 0x2000
                                      +---+---+- -+---+
                     +--------------->|   |   | … | 0 |
argv @ 0x1000        |                +---+---+- -+---+
+---------------+    |            
| 0x2000      -------+                *(argv[1]) @ 0x2100
+---------------+                     +---+---+- -+---+
| 0x2100      -----------+----------->|   |   | … | 0 |
+---------------+        |            +---+---+- -+---+
| 0x2200      -----------)----+
+---------------+        |   |        *(argv[2]) @ 0x2200
| ⋮             |        |   |        +---+---+- -+---+
                         |   +------->|   |   | … | 0 |
rb @ 0x3000              |   |        +---+---+- -+---+
+---------------+        |   |
| 0x4000      -------+   |   |        *rb @ 0x4000
+---------------+    |   |   |        +---------------+
                     +---)---)------->|               |
threads @ 0x5000     |   |   |        +---------------+
+---------------+    |   |   |    
|  +-----------+|    |   |   |    
|rb| 0x4000  --------+   |   |
|  +-----------+|    |   |   |
|fn| 0x2100  --------)---+   |
|  +-----------+|    |       |
+---------------+    |       |
|  +-----------+|    |       |
|rb| 0x4000  --------+       |
|  +-----------+|            |
|fn| 0x2200  ----------------+
|  +-----------+|
+---------------+
| ⋮             |

(假设 threads 是数组而不是指向数组的指针。这不会影响 post 的其余部分。)

当然,所有地址都是编造的。但是您可以看到不止一次变量具有相同的值地址。因为让多个指针指向同一个内存块是完全没问题的。我们需要做的就是复制指针(地址)。

要复制一个指针,你需要做的就是

dst = src;

所以你只需要

threads[length].rb = rb;
threads[length].fn = argv[index];

同时

memmove(&threads[length].rb, &rb,          sizeof(threads[length].rb));
memmove(&threads[length].fn, &argv[index], sizeof(threads[length].fn));

memmove(&threads[length].rb, &rb,          sizeof(rb));
memmove(&threads[length].fn, &argv[index], sizeof(argv[index]));

相当于赋值,做那么复杂的事情没有意义:

(注意使用sizeof(argv[index])而不是strlen(argv[index])。这是我们正在复制的指针,所以我们需要指针的大小。)

警告来自试图将 0x2100 缓冲区中的字符串复制到 0x2100 缓冲区。请记住 threads[length].fnargv[index]memmove.

之后都具有相同的值(地址)