Linux 中的 C++ reinterpret_cast 核心,但 MAC 中的 运行 成功

C++ reinterpret_cast core in Linux, but run succsee in MAC

在某些情况下,我想要 malloc 一块内存,例如:内存的第一部分将包含字符串,第二部分内存将包含长整型数据。所以,我尝试下面的演示代码。

下面的代码可以 运行 在 MAC 中成功,但在 Linux 中可以进行核心转储。

valgrind 资源:

valgrind result screenshot

其中:

  1. 第 7 行是:str[0] = key.data();
  2. 第 13 行是 test_cache(cache, "test");
#include <iostream>
#include <stdlib.h>  
#include <stdio.h>
#include <string>

void test_cache(char *cache, std::string key) {
  std::string* str = reinterpret_cast<std::string*> (cache);
  str[0] = key.data();
}

int main()
{
  char *cache = reinterpret_cast<char *> (calloc(1000, 1));
  test_cache(cache, "test");
  std::string* str = reinterpret_cast<std::string*> (cache);
  printf("%s\n",str[0].c_str());
  free(cache);
}

请好好阅读C++ programming book, then see this C++ reference and the documentation of your C++ compiler (perhaps GCC) and debugger (e.g. GDB). You are right in using valgrind, but of course you should read its documentation (and also consider using address sanitizers, and be aware of ASLR).

我的建议是在编译 C++ 代码时启用所有警告和调试信息。

对于 GCC,这意味着使用 g++ -Wall -Wextra -g 编译您的 C++ 代码。

在C++中,最喜欢使用动态内存分配的方式不是使用C中的mallocfree函数,而是使用::operator new. There are cases where you could redefine your new. Be however aware of the C++ rule of five作为一个优秀的编码规则。

实际上,在一些 C++ 实现中,new 可能会在调用构造函数之前调用 malloc,而 delete 可能会在调用析构函数之后调用 free。当 malloc 失败时,new 应该抛出异常。

另见 this draft report for more detailed explanations, focused on recent GCC (e.g. GCC 10 2020 年夏季)。

在 C++ 中,您想利用强大的标准 C++ 库,所以使用 std::string for strings, and learn to use C++ containers and smart pointers

std::string* str = reinterpret_cast<std::string*> (cache);

无法工作(因为除了字节内存区域之外,标准字符串还知道它的大小)。你可能想要

 auto str = new std::string(cache);

 std::string str(cache);

害怕 undefined behavior and read later the C++11 standard n3337(或更晚的)。

考虑在整个 C++ 程序中使用静态源代码分析器,如 Frama-C++ or the Clang static analyzer. If you are allowed to use GCC 10, consider using its static analysis facilities, or writing your own GCC plugin for static analysis purposes. If, in summer 2020, your GCC is older than GCC 10, do compile GCC 10 from its source code(在获得经理或客户的许可后)。当然,编写一个 GCC 插件可能需要几个月的时间,所以对于大型 C++ 程序来说是值得的。

顺便说一句,两者都是 GCC and Clang are open source C++ 编译器,因此您可以下载并研究它们的源代码。特别是,请浏览 std::string

的实现细节