Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamically creating object instances causes segmentation fault #154

Closed
spyrospav opened this issue Apr 2, 2022 · 3 comments
Closed

Dynamically creating object instances causes segmentation fault #154

spyrospav opened this issue Apr 2, 2022 · 3 comments

Comments

@spyrospav
Copy link

spyrospav commented Apr 2, 2022

Basically, I was trying to use run Nidhugg on a class implementation and fell on this error. A minimal example to reproduce the segmentation fault I encountered is the following:

class Test{
  public:
    Test(){
      x = 1;
    }

  private:
    int x;
};

int main() {
  Test *t = new Test();

  return 0;
}

The error that Nidhuggs displays is the following :

image

Note that if I remove the x variable only the warning remains and Nidhugg does not produce the segmentation fault. Also, if I instantiate my class object without new then Nidhugg does not produce neither a warning nor a segmentation fault (however it is crucial for my application to dynamically create the object).

@spyrospav spyrospav changed the title Creating object instances with new causes segmentation fault Dynamically creating object instances causes segmentation fault Apr 2, 2022
@margnus1
Copy link
Contributor

margnus1 commented Apr 2, 2022

It is a known flaw of nidhugg's frontend (#104, #105) that if you want to use any part of the C++ standard library that is not header-only, you need to compile the standard library to IR yourself and link it to your program under test.

Since the c++ standard library does not define operator new(unsigned long) (which mangles to _Znwm) in the header files, Nidhugg is using its last hail-mary for undefined functions in the program under test, calling the compiled version as a black-box. However, it is not allowed for black-box functions to malloc (like operator new(unsigned long) does). In fact, the black-box support is very limited, and if you have any black-box calls you're unlikely to get the behaviour you want from nidhugg.

As a workaround, you can define your own new and delete in your program under test:

void* operator new(std::size_t sz)
{
    if (sz == 0)
        ++sz; // avoid std::malloc(0) which may return nullptr on success
 
    if (void *ptr = std::malloc(sz))
        return ptr;
 
    throw std::bad_alloc{};
}
void operator delete(void* ptr) noexcept
{
    std::free(ptr);
}

I'll think about a medium-term solution so that people can at least call new without workarounds.

@spyrospav
Copy link
Author

Thanks, that workaround does the job.

P.S. Is it std::bad_alloc() instead of std::bad_alloc{} ?

@margnus1
Copy link
Contributor

margnus1 commented Apr 2, 2022

I suppose either should work. I got the code from cppreference

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants