gpt4 book ai didi

c++ - 访问 string::c_str() 的结果时出现 valgrind 内存访问错误

转载 作者:太空狗 更新时间:2023-10-29 20:01:37 27 4
gpt4 key购买 nike

因此,当我遇到最奇怪的内存问题时,我正在编写一些网络代码,但我无法正确理清这里可能发生的事情。我想知道 c_str() 中是否有某种我没有正确观察到的含义。

所以这里是有错误的代码。 (还有一个释放错误,但我把这个功能作为一个宠物项目)。

#include <netdb.h>       // for AF_UNSPEC, AF_INET, AF_INET6
#include <stdint.h> // for uint16_t, etc.
#include <sys/types.h> // for AF_UNSPEC, AF_INET, AF_INET6
#include <sys/socket.h> // for AF_UNSPEC, AF_INET, AF_INET6
#include <string> // for std::strin
#include <stdio.h>
#include <string.h>
int main() {
uint16_t port = 2098;


struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET6; // IPv6 (also handles IPv4 clients)
hints.ai_socktype = SOCK_STREAM; // stream
hints.ai_flags = AI_PASSIVE; // use wildcard "INADDR_ANY"
hints.ai_protocol = IPPROTO_TCP; // tcp protocol
hints.ai_canonname = nullptr;
hints.ai_addr = nullptr;
hints.ai_next = nullptr;

const char* port_num = (std::to_string(port)).c_str();

struct addrinfo *result;
int res = getaddrinfo(nullptr, port_num, &hints, &result);

printf("HI\n");
}

如果您对生成的二进制文件进行 valgrind,您会得到:

==45919== Invalid read of size 1
==45919== at 0x573BA5C: getaddrinfo (in /usr/lib64/libc-2.17.so)
==45919== by 0x400C95: main (in /homes/iws/kieruc/Coding/a.out)
==45919== Address 0x5a22058 is 24 bytes inside a block of size 29 free'd
==45919== at 0x4C2B16D: operator delete(void*) (vg_replace_malloc.c:576)
==45919== by 0x4EF3B62: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib64/libstdc++.so.6.0.19)
==45919== by 0x400C7C: main (in /homes/iws/kieruc/Coding/a.out)
==45919== Block was alloc'd at
==45919== at 0x4C2A1E3: operator new(unsigned long) (vg_replace_malloc.c:334)
==45919== by 0x4EF3A18: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib64/libstdc++.so.6.0.19)
==45919== by 0x400FFE: char* std::string::_S_construct<char*>(char*, char*, std::allocator<char> const&, std::forward_iterator_tag) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400F14: char* std::string::_S_construct_aux<char*>(char*, char*, std::allocator<char> const&, std::__false_type) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400EDD: char* std::string::_S_construct<char*>(char*, char*, std::allocator<char> const&) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400E8F: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<char*>(char*, char*, std::allocator<char> const&) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400E20: std::string __gnu_cxx::__to_xstring<std::string, char>(int (*)(char*, unsigned long, char const*, __va_list_tag*), unsigned long, char const*, ...) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400CDE: std::to_string(int) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400C60: main (in /homes/iws/kieruc/Coding/a.out)
==45919==
==45919== Invalid read of size 1
==45919== at 0x573BACA: getaddrinfo (in /usr/lib64/libc-2.17.so)
==45919== by 0x400C95: main (in /homes/iws/kieruc/Coding/a.out)
==45919== Address 0x5a22058 is 24 bytes inside a block of size 29 free'd
==45919== at 0x4C2B16D: operator delete(void*) (vg_replace_malloc.c:576)
==45919== by 0x4EF3B62: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib64/libstdc++.so.6.0.19)
==45919== by 0x400C7C: main (in /homes/iws/kieruc/Coding/a.out)
==45919== Block was alloc'd at
==45919== at 0x4C2A1E3: operator new(unsigned long) (vg_replace_malloc.c:334)
==45919== by 0x4EF3A18: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib64/libstdc++.so.6.0.19)
==45919== by 0x400FFE: char* std::string::_S_construct<char*>(char*, char*, std::allocator<char> const&, std::forward_iterator_tag) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400F14: char* std::string::_S_construct_aux<char*>(char*, char*, std::allocator<char> const&, std::__false_type) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400EDD: char* std::string::_S_construct<char*>(char*, char*, std::allocator<char> const&) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400E8F: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<char*>(char*, char*, std::allocator<char> const&) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400E20: std::string __gnu_cxx::__to_xstring<std::string, char>(int (*)(char*, unsigned long, char const*, __va_list_tag*), unsigned long, char const*, ...) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400CDE: std::to_string(int) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400C60: main (in /homes/iws/kieruc/Coding/a.out)

但是如果我把代码改成这样

std::string portstr = std::to_string(port);

struct addrinfo *result;
int res = getaddrinfo(nullptr, portstr.c_str(), &hints, &result);

那么就没有内存错误了。我不太明白为什么。

另一件需要注意的事情是,如果我尝试使用 char* 编译带有 const char* 变量的版本,您会收到一条警告,指出该变量应该是常量.

这是怎么回事?

最佳答案

c_str 返回的缓冲区仅在关联的 std::string 对象存在期间有效。还有这里

const char* port_num = (std::to_string(port)).c_str();

一个临时字符串对象被创建,它的缓冲区地址被获取,然后它在完整表达式的末尾消亡。使用悬挂指针会出现内存错误。

如果你想使用一个临时的std::string,它必须在你使用缓冲区的完整表达式中创建:

int res = getaddrinfo(nullptr, std::to_string(port).c_str(), &hints, &result)

关于c++ - 访问 string::c_str() 的结果时出现 valgrind 内存访问错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56500825/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com