Search code examples
c++reinterpret-cast

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


In some case,I want malloc a block memory, example: first part of memory will contains strings, second part memory will contains long type data. so, i try the demo code below.

the code below can run success in MAC, but core dump in Linux.

valgrind res:

valgrind result screenshot

where:

  1. line 7 is: str[0] = key.data();
  2. line 13 is 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);
}

Solution

  • Please read a good 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).

    My recommendation is to enable all warnings and debug information when compiling your C++ code.

    With GCC, that means using g++ -Wall -Wextra -g to compile your C++ code.

    In C++, the favorite way to use dynamic memory allocation is not to use the malloc and free functions from C, but to use ::operator new. There are cases where you could redefine your new. Be however aware of the C++ rule of five as an excellent coding rule.

    In practice, on several C++ implementations, new might call malloc before calling the constructor and delete might call free after calling the destructor. When malloc fails, new should throw an exception.

    See also this draft report for more detailed explanations, focused on recent GCC (e.g. GCC 10 in summer 2020).

    In C++, you want to take advantage of the powerful standard C++ library, so use std::string for strings, and learn to use C++ containers and smart pointers.

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

    cannot work (since a standard string knows its size in addition of the bytes memory zone). You may want

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

    or

     std::string str(cache);
    

    Be scared of undefined behavior and read later the C++11 standard n3337 (or a later one).

    Consider using, on your entire C++ program, static source code analyzers like 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 (after getting permission from your manager or client). Of course, writing a GCC plugin may take months of work, so is worthwhile for large C++ programs.

    BTW, both GCC and Clang are open source C++ compilers, so you are allowed to download then study their source code. In particular, do glance inside the implementation details of std::string