Valgrind 在尝试将字符串复制到结构成员变量时警告重叠
Posted
技术标签:
【中文标题】Valgrind 在尝试将字符串复制到结构成员变量时警告重叠【英文标题】:Valgrind warns of overlap when trying to copy a string into a struct member variable 【发布时间】:2021-12-29 15:57:38 【问题描述】:这是结构的外观供参考:
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 结果。有什么解决办法吗?
【问题讨论】:
您确定要复制到&threads[length].file_name
而不是threads[length].file_name
? char *file_name;
成员是一个指针。
...第二个参数也有同样的问题。你为什么要使用 strcpy 来跟进 memmove?
@WeatherVane 我想复制argue[index]的实际值。 memmove
不是在移动字节,所以我需要那个变量所在的地址吗?
要复制argv[index]
的值(指针又名地址),您只需要threads[length].file_name = argv[index];
。但是,如果您想将指向的字符从一个缓冲区复制到另一个缓冲区,那么您需要 memmove(threads[length].file_name, argv[index], strlen(argv[index]));
或 strcpy(threads[length].file_name, argv[index]);
简短回答:只需threads[length].file_name = argv[index];
(相当于您拥有的memmove
)。另外,最好将其设为const char*
【参考方案1】:
这就是你想要的结果:
(我在帖子中使用“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
是一个数组,而不是指向数组的指针。这不会影响帖子的其余部分。)
当然,所有地址都是虚构的。但是您可以看到不止一次变量具有相同的值地址。因为让多个指针指向同一个内存块是非常好的。我们需要做的就是复制指针(地址)。
要复制一个指针,你需要做的就是
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
之后具有相同的值(地址)。
【讨论】:
以上是关于Valgrind 在尝试将字符串复制到结构成员变量时警告重叠的主要内容,如果未能解决你的问题,请参考以下文章