尝试将字符串复制到结构成员变量时,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].fn
和 argv[index]
在 memmove
.
之后都具有相同的值(地址)
这是结构的样子以供参考:
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].fn
和 argv[index]
在 memmove
.