I'm trying to build a lambda that wraps some input functions with some pre/post actions.
My code works fine and pre/post actions get called correctly if I try to wrap a regular function/lambda.
However, when I try to apply my decorating lambda to a function that it produced before, my program crashes after complaining that the inner function was freed at some point (this is confirmed by valgrind).
What puzzles me is that the crash depends on the compiler: the code works perfectly fine with Xcode 6 clang (clang-3.6 based), but crashes on linux using clang++-3.6 and g++4.8.4.
I've made a small program that reproduces the behaviour:
#include <iostream>
#include <string>
#include <functional>
using namespace std;
typedef function<void(void)> NestedFn;
int main()
{
// Create a cfunction
auto lambdaFactory = [&](string title, NestedFn nestedFunc)
{
// title is copied to the new lambda
return [&, title]() {
cerr << "------------ START -----------" << endl;
cerr << "Inside: " << title << endl;
nestedFunc();
cerr << "------------- END ------------" << endl;
};
}
auto l1 = lambdaFactory("1", []() { cerr << "\tNest (1)" << endl; });
auto l2 = lambdaFactory("2", []() { cerr << "\tNest (2)" << endl; });
l1(); // Works ok, displays, START, 1, END
l2(); // Same here
auto dobble = lambdaFactory("Dobble", l1);
dobble(); // Display START, Inside Dobble, START,
// then crashes when trying to execute nestedFunc(), ie l1()
}
What did I get wrong in the variable scope management ? And is there any reason for this program not crashing using Apple's LLVM ?
EDIT
For the record, here is the correct lambdaFactory after the correction suggested by T.C. :
auto lambdaFactory = [&](string title, NestedFn nestedFunc)
{
return [&, title, nestedFunc]() {
cerr << "------------ START -----------" << endl;
cerr << "Inside: " << title << endl;
nestedFunc();
cerr << "------------- END ------------" << endl;
};
};
The lambda returned by a call to lambdaFactory captures nestedFunc by reference, but nestedFunc is a function argument passed by value, so it goes out of scope as soon as the call to lambdaFactory returns, resulting in a dangling reference.
And is there any reason for this program not crashing using Apple's LLVM ?
Undefined behavior is undefined. You are also likely using two different standard library implementations (libc++ on Mac/libstdc++ on linux), so there are likely differences in how everything is laid out etc.
Related
The following code should be almost a copy of what the book Functional Programming in C++ presents at the end of Chapter 6 section 1:
#include <iostream>
#include <utility>
#include <mutex>
template<typename F>
class lazy_val {
private:
F m_computation;
mutable decltype(m_computation()) m_cache;
mutable std::once_flag m_value_flag;
public:
lazy_val(F f)
: m_computation(f)
{}
operator const decltype(m_computation())& () const {
std::call_once(m_value_flag, [this](){
m_cache = m_computation();
});
return m_cache; // the execution never gets to this line
}
};
int expensive() {
std::cout << "expensive call...\n";
return 7;
}
int main() {
std::cout << "non memoized" << '\n';
std::cout << expensive() << '\n';
std::cout << expensive() << '\n';
std::cout << expensive() << '\n';
const auto expensive_memo = lazy_val(expensive);
std::cout << "memoized" << '\n';
std::cout << expensive_memo << '\n'; // crash happens here
std::cout << expensive_memo << '\n';
std::cout << expensive_memo << '\n';
}
However, when I execute it (the compilation is goes fine), I get this error:
non memoized
expensive call...
7
expensive call...
7
expensive call...
7
memoized
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error -1
Aborted (core dumped)
If ignore concurrency issues and only rely on a mutable bool m_cache_initialized; initialized to false, and a if (!m_cache_initialized) { m_cache = m_computation(); m_cache_initialized = true; }, then everything works.
This makes me think that the problem is with how I use std::call_once/std::once_flag in my code. However I don't see how it is different from what is shown in the book (constructor in Listing 6.2, but without the line initializing the m_cache_initialized to false, and the rest of the class is at the bottom of page 125 and top of 126).
You must be using Linux and gcc. An "undocumented" feature of this implementation is that any C++ code that uses any thread-related stuff must be explicitly linked with -lpthread.
I reproduced your exact crash on Linux, after compiling (with -std=c++17) and linking without -lpthread. The shown code runs fine, if explicitly linked with -lpthread.
I am learning C++ with pointers and trying to program a small game. I have a class PlayerManager which should create players and save them in a file.
The code compiles but when I call the method savePlayer, the pointer inside the method is valid but I cannot access the object to which the pointer is pointing.
I have searched for similar problems on internet but did not find anything similar. I may not be looking for the right keywords as I have no idea where this comes from.
I checked before the function is called and the pointer is working and I can access the object.
Inside the calling function, the pointer still has the right address but I cannot access the object. Nothing is returned.
After the calling function the pointer is still valid and the object accessible. (see //Comments in the code below)
Here are my two functions inside my PlayerManager class.
void PlayerManager::createPlayer()
{
Player *playerPtr = new Player();
std::string name;
std::cout << "Name: ";
std::cin >> name; // I entered for instance John
std::cout << std::endl;
playerPtr->setName(name);
std::cout << "PlayerPtr name before savePlayer: " << playerPtr->getName() << std::endl; // Outputs John
std::cout << "playerPtr before savePlayer: " << playerPtr << std::endl; // Ouputs the address
this->savePlayer(playerPtr);
std::cout << "PlayerPtr name after savePlayer but inside createPlayer: " << playerPtr->getName() << std::endl; // Outputs: John
delete playerPtr;
}
void PlayerManager::savePlayer(Player* playerPtr) // the called method
{
std::cout << "playerPtr inside savePlayer: " << playerPtr << std::endl; // Outputs the address
std::cout << "PlayerPtr name inside savePlayer: " << playerPtr->getName() << std::endl; // Outputs nothing
std::string const fileName = "Players/"+playerPtr->getName()+".txt";
std::cout << fileName << std::endl; // Outputs Players/.txt
std::ofstream myFile = std::ofstream(fileName.c_str());
if(myFile)
{
std::cout << "Enregistrement du nouveau joueur." << std::endl; // The code launches but no file is created.
myFile << "{"<< std::endl;
myFile << "name: " + playerPtr->getName() <<std::endl;
} else {
std::cout << "Erreur d'enregistrement du fichier." << std::endl;
}
}
I would like to be able to access the object created in createPlayer method inside the savePlayer method by passing a pointer but I just get an empty string for
playerPtr->getName()
I don't understand how the object is accessible before the call of the method and after but not inside as the address is still valid.
EDIT1
Thank you for guiding me to the obvious mistake !
Because of recuring crash of code:blocks my getName() method was deleted before I could save it and I did not think about checking it. By writing the following getName() it worked:
std::string Player::getName() const
{
return m_name;
}
Yet I do not understand why and How I got an output in createPlayer() although the method getName() was empty. Is this normal ?
EDIT 2
I'll create a new question for this strange behavior.
The code you have should work fine. My only guess is that there's something fishy about your getter function getName().
I presume you have something along these lines?
const std::string &getName() const
{
return name;
}
Online code example: https://rextester.com/INHG32142
I created decorator function to add functionality to existing functions. The program outputs correct function pointer addresses along with an elapsed time to iterate 10 x helloworld as expected.
Yet, if I change decorator function to take the original_function by value (FunctionPointer original_function), the program terminates with a segmentation fault, which I don't get the reason why it fails.
#include <iostream>
#include <chrono>
typedef void (*FunctionPointer)();
auto
decorator(FunctionPointer && original_function) // if changed to FunctionPointer original_function, it causes segmentation fault when the closure(lambda expression) is called later on
{
std::cout << "Decorator: " << (void*)original_function << std::endl; // 0x558072fb0b90
return [&]()
{
std::cout << "Decorator: " << (void*)original_function << std::endl; // 0x558072fb0b90 but 0x0 when original_function passed by value
auto t0 = std::chrono::high_resolution_clock::now();
original_function();
auto duration = std::chrono::high_resolution_clock::now() - t0;
std::cout << "\nElapsed " << duration.count() * 1000.0f << " ms\n";
};
}
void
helloworld(void)
{
for (auto i = 0; i < 10; i++)
std::cout << "Hello, World!\n";
}
int
main(void)
{
std::cout << "Main: " << (void*)helloworld << std::endl; // 0x558072fb0b90
auto my_helloworld = decorator(helloworld);
my_helloworld();
return 0;
}
The difference is that when you pass the function by value, the parameter passed into the lambda is a reference to the function parameter, which goes out of scope when decorator returns. When you later call the returned lambda, you reference this out of scope variable, which is Undefined Behavior.
It works when you pass by universal reference, the parameter passed to decorator is a reference, which is passed to the lambda. So it is still valid later when you call the lambda.
You may be able to change your lambda to pass by value (use [=]) to get the changed version to work.
I'm quite new to the world of pointers in C/C++ so this may be quite an easy question for you:
The following C++-Code works normally
#include <iostream>
int main()
{
int theInt = 1337;
int & theReference = theInt;
int * thePointer = &theInt;
std::cout << "int: " << theInt << "\n";
std::cout << "referenz: " << theReference << "\n";
std::cout << "pointer: " << *thePointer << "\n";
std::cout << "pointer: " << *thePointer << "\n";
//std::cout << "foo" << "\n";
return 0;
}
but stops working when changing
//std::cout << "foo" << "\n";
to
std::cout << "foo" << "\n";
.
By "stops working" I mean: "is blocked by my norton security as a potential threat" (resulting in a return code of "0x76F531AF" if this is any help). Since norton normally doesn't interfere withe my programming I assume the double use of the int pointer in cout somehow results in a segfault...
Thx for your help!
PS:
I use Code::Blocks on Windows 8.1 with the GCC compiler and GDB debugger from TDM-GCC (version 4.7.1, 32 bit).
EDIT: removed deletion of pointer -> problem remains.
You can only delete objects created on the heap (using new or C-style malloc and such).
// allocate on the heap
int *intOnTheHeap = new int;
// do some stuff with it
*intOnTheHeap = 0;
(*intOnTheHeap)++;
std::cout << *intOnTheHeap << std::endl;
// deallocate
delete intOnTheHeap;
If you take a pointer to a local variable, it will point to an entry on the stack. You don't need to and shouldn't deallocate that memory yourself. The memory is "freed" by changing the stackpointer automatically when your variable runs out of scope (at the end of the function).
void myFunction() {
int localVariable;
int *pointerToLocalVariable = &localVariable;
// forbidden and unnecessary:
//delete pointerToLocalVariable;
// here (end of the block) the memory on the stack
// will be freed automatically
}
Since I got the same error after Norton-Interception in totally different contexts, this seems to be a case of Code::Blocks Norton incompatibility.
I am playing with TagLib (on Windows, built with MingW). I am trying to get TagLib to recognize when there is no ID3v1 or ID3v2 information in an MP3 file. According to the TagLib documentation, the ID3v2Tag() function in an MPEG File object should return a NULL pointer when there is no ID3v2 information in the file.
Unfortunately, this is not occurring. I have some test MP3 files I have made that I use in my code (I have made the files available):
blank.mp3 (download), no ID3v1 or ID3v2 information at all. I can confirm this by doing a plain text search for "TAG" and "ID3" in the files binary content.
only_album_id3v2.mp3 (download), has ID3v2 information (only the album is set)
only_album_id3v1.mp3 (download), has ID3v1 information (only the album is set)
Here is my code.
#include <iostream>
#include <mpeg/mpegfile.h>
#include <mpeg/id3v2/id3v2tag.h>
using namespace std;
int main()
{
cout << "Test." << endl;
TagLib::MPEG::File a("tests/other/blank.mp3");
TagLib::MPEG::File b("tests/id3v2/only_album_id3v2.mp3");
TagLib::MPEG::File c("tests/id3v1/only_album_id3v1.mp3");
TagLib::ID3v2::Tag * at = a.ID3v2Tag();
TagLib::ID3v2::Tag * bt = b.ID3v2Tag();
TagLib::ID3v2::Tag * ct = c.ID3v2Tag();
cout << at->album() << endl;
cout << bt->album() << endl;
cout << ct->album() << endl;
cout << "The program is done.";
return 0;
}
Running this program should break, due to a NULL pointer error on cout << at->album() << endl;, but it runs just fine. Also, when I cout << ct << endl;, it returns a memory address.
Here is the output:
Test.
test album id3v2
The program is done.
EDIT:
Here is a new test.
#include <iostream>
#include <mpeg/mpegfile.h>
#include <mpeg/id3v2/id3v2tag.h>
using namespace std;
int main()
{
cout << "Test." << endl;
TagLib::MPEG::File a("tests/other/blank.mp3");
TagLib::MPEG::File b("tests/id3v2/only_album_id3v2.mp3");
TagLib::MPEG::File c("tests/id3v1/only_album_id3v1.mp3");
TagLib::ID3v2::Tag * at = a.ID3v2Tag();
TagLib::ID3v2::Tag * bt = b.ID3v2Tag();
TagLib::ID3v2::Tag * ct = c.ID3v2Tag();
if(at == NULL)
{
cout << "at is NULL.";
}
else
{
cout << "at is not NULL.";
}
cout << endl;
if(bt == NULL)
{
cout << "bt is NULL.";
}
else
{
cout << "bt is not NULL.";
}
cout << endl;
if(ct == NULL)
{
cout << "ct is NULL.";
}
else
{
cout << "ct is not NULL.";
}
cout << endl;
cout << "The program is done.";
return 0;
}
And here is the output.
Test.
at is not NULL.
bt is not NULL.
ct is not NULL.
The program is done.
I examined TagLib's code briefly.
I know nothing about it and never used it, but the code looks buggy to me. Here's why -
In MPEG::File::read(), we are looking for a tag - d->ID3v2Location = findID3v2();. If it doesn't exist, it isn't added to the tags vector. This is the check - if(d->ID3v2Location >= 0).
However, at the end of the function, just before returning, we have -
// Make sure that we have our default tag types available.
ID3v2Tag(true);
ID3v1Tag(true);
Now, Id3v2Tag(create) with a true parameter, actually calls return d->tag.access(ID3v2Index, create);. The access() function is -
template <class T> T *access(int index, bool create)
{
if(!create || tag(index))
return static_cast<T *>(tag(index));
set(index, new T);
return static_cast<T *>(tag(index));
}
So when create is true, we are creating a brand new, empty tag and placing it in the vector (using the set() function).
This means that no matter whether the file contains the tags or not, they are added to the vector. This isn't the documented behavior. Looks like a bug.
I don't know why these two lines are needed there - looking at the history of this file might hint as to why they were added, but I didn't do that.
Anyway, I want to stress that I never actually executed this code. This is based on purely statically reading only very small parts, without being aware of large scale issues.
I think that opening a bug report can't hurt.
Using a null pointer doesn't necessarily result in any error you can see; it's undefined behavior. It might appear to work, or it might do something really really weird.
In this case the compiler is probably generating a call to TagLib::ID3v2::Tag::album with the this pointer set to null, but even this is not guaranteed. What happens inside the function is anyone's guess.
If the function can return NULL, you should be explicitly checking for it and doing something different.
Taglib create an "Empty" ID3v2Tag and ID3v1Tag in the object if the file do not have one.
I am having simmilar problem and hopefully I've found workaround for ID3v1/ID3v2 presence checking.
It's method virtual bool TagLib::Tag::isEmpty() const