The program has unexpectedly finished in QDateTime::currentdatetime - c++

I am running a thread, but sometimes the program dies. I hope you could tell me why that exit. Error
glibc detected /home/hsr/CMBU-build-desktop-Qt_4_8_1_in_PATH__System__Release/CMBU: corrupted double-linked list: 0x00000000026192e0
Backtrace:
00400000-00437000 r-xp 00000000 08:01 2499001 /home/hsr/CMBU-build-desktop-Qt_4_8_1_in_PATH__System__Release/CMBU
00636000-00637000 r--p 00036000 08:01 2499001 /home/hsr/CMBU-build-desktop-Qt_4_8_1_in_PATH__System__Release/CMBU
00637000-00638000 rw-p 00037000 08:01 2499001 /home/hsr/CMBU-build-desktop-Qt_4_8_1_in_PATH__System__Release/CMBU
02410000-02c5f000 rw-p 00000000 00:00 0 [heap]
7fe2ff74d000-7fe2ffb72000 r--p 00000000 08:01 2755027 /usr/share/fonts/truetype/nanum/NanumGothic.ttf
7fe2ffb72000-7fe300000000 rw-s 00000000 00:04 6717449 /SYSV00000000 (deleted)
7fe300000000-7fe300022000 rw-p 00000000 00:00 0
7fe300022000-7fe304000000 ---p 00000000 00:00 0
7fe304000000-7fe304132000 rw-p 00000000 00:00 0
7fe304132000-7fe308000000 ---p 00000000 00:00 0
7fe308000000-7fe308022000 rw-p 00000000 00:00 0
7fe308022000-7fe30c000000 ---p 00000000 00:00 0
7fe30c26c000-7fe30c2cc000 rw-s 00000000 00:04 6750219 /SYSV00000000 (deleted)
7fe30c2cc000-7fe30c6e4000 r--p 00000000 08:01 2755028 /usr/share/fonts/truetype/nanum/NanumGothicBold.ttf
7fe30c6e4000-7fe30c6e5000 ---p 00000000 00:00 0
7fe30c6e5000-7fe30cee5000 rw-p 00000000 00:00 0
void Thread::run()
{
while (!stopped) {
if(messageStr==tr("A")) {
MainCMBU::ui->dateTimeEdit->setDateTime(QDateTime::currentDateTime());
msleep(1000);
}
}
//std::cerr << qPrintable(messageStr);
stopped = false;
}

Use a QTimer to update your UI in UI thread
Use that same QTimer to do work, if you plan on doing work
If there is too much work for GUI, use QtConcurrent::run() or similar to do non-GUI work. Use a QFutureWatcher if you need to know when that asynchronous operation is complete.
Sleeping in a thread like you are doing is generally bad design.
In Qt, you cannot access GUI thread elements from non-GUI thread. GUI is NOT threadsafe.

Related

malloc error when using std::shared_ptr

I've decided to parallelize a huge program I wrote and eventually I came across the new C++11 smart pointers.
I had a routine that should be executed many times (usually above 1000 times) that is somewhat expensive. It was ran in a dead simple for loop, what I did was to install this for loop in a method which would be ran by some worker threads.
Did it so, made some parameters wrapped by a std::shared_ptr, cared for race conditions, everything seemed fine.
But now, some times, process will be aborted and I am given one of the following errors:
Process finished with exit code 139 (interrupted by signal 11:
SIGSEGV)
or
malloc.c:2395: sysmalloc: Assertion `(old_top == initial_top (av) &&
old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse
(old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed.
All of these errors occur while the parallel for is ongoing; not before, not right in the beginning, not in the end, but somewhere in between, which smells me like a race condition not covered.
The program is huge, but I created a miniature of it that is able to reproduce the problem:
#include <iostream>
#include <vector>
#include <unordered_map>
#include <thread>
#include <set>
#include <memory>
#include <atomic>
namespace std {
template <>
struct hash<std::multiset<unsigned long>>
{
std::size_t operator()(const std::multiset<unsigned long>& k) const
{
std::size_t r = 0;
bool shift = false;
for (auto&& it : k) {
r = (r >> !shift) ^ (std::hash<unsigned long>()(it) << shift);
shift = !shift;
}
return r;
}
};
}
typedef std::unordered_map<std::multiset<unsigned long>, int*> graphmap;
std::multiset<unsigned long>* bar(int pos) {
std::multiset<unsigned long> *label = new std::multiset<unsigned long>;
label->insert(pos%5);
label->insert(pos%2);
return label;
}
void foo(std::shared_ptr<graphmap> &kSubgraphs, int pos) {
int *v = (*kSubgraphs)[*bar(pos)];
if(v == nullptr) {
v = new int[pos+1]();
v[0]++;
} else {
v[pos]++;
}
}
void worker(std::shared_ptr<std::atomic_int> *counter, int n, std::shared_ptr<graphmap> *kSubgraphs)
{
for (int pos = (*counter)->fetch_add(1); pos <= n; pos = (*counter)->fetch_add(1)) {
if (pos%100==0) std::cout << pos << std::endl;
foo(*kSubgraphs, pos);
}
}
int main() {
int n = 1000;
std::vector<std::thread> threads;
std::shared_ptr<graphmap> kSubgraphs = std::make_shared<graphmap>();
std::shared_ptr<std::atomic_int> counter = std::make_shared<std::atomic_int>(0);
for (int i=0; i<5; i++) {
foo(kSubgraphs, n);
}
for (int i=0; i<4; i++) {
threads.push_back(std::thread(worker, &counter, n, &kSubgraphs));
}
for(auto& th : threads) th.join();
return 0;
}
This code basically mimics the behavior of the original code, which is to use an unordered_map keyed by a multiset with values that are pointers to int arrays. First some keys are inserted and the array initialized (maybe the problem is caused by the way I am initializing it?) and finally the worker threads run to update a unique position of the array of an entry of the unordered_map.
Two threads may access the same map entry simultaneously, but they will never write to the same index of the array at the same time.
Different from the original code, this code won't throw any errors when running over internet compilers such as ideone.com, I also tried to run it from CLion ide and no errors will occur (maybe it can occur errors if one tries enough times), but I got similar error as the original when running from the command line multiple times. I compiled it with:
g++ -std=c++11 -pthread -o test.exe test.cpp
And after running several times it eventually gives this error:
*** Error in `./test.exe': double free or corruption (fasttop): 0x00000000006a2d30 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x77725)[0x7fccc9d4f725]
/lib/x86_64-linux-gnu/libc.so.6(+0x7ff4a)[0x7fccc9d57f4a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7fccc9d5babc]
./test.exe[0x404e9e]
./test.exe[0x40431b]
./test.exe[0x4045ed]
./test.exe[0x407c6c]
./test.exe[0x4078d6]
./test.exe[0x40742a]
./test.exe[0x40869e]
./test.exe[0x4086be]
./test.exe[0x4085dd]
./test.exe[0x40842d]
./test.exe[0x4023a2]
./test.exe[0x401d55]
./test.exe[0x401c4a]
./test.exe[0x401c66]
./test.exe[0x401702]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7fccc9cf8830]
./test.exe[0x401199]
======= Memory map: ========
00400000-0040f000 r-xp 00000000 08:05 12202697 /home/rodrigo/test.exe
0060e000-0060f000 r--p 0000e000 08:05 12202697 /home/rodrigo/test.exe
0060f000-00610000 rw-p 0000f000 08:05 12202697 /home/rodrigo/test.exe
00691000-006c3000 rw-p 00000000 00:00 0 [heap]
7fcca8000000-7fcca8089000 rw-p 00000000 00:00 0
7fcca8089000-7fccac000000 ---p 00000000 00:00 0
7fccb0000000-7fccb008b000 rw-p 00000000 00:00 0
7fccb008b000-7fccb4000000 ---p 00000000 00:00 0
7fccb8000000-7fccb8089000 rw-p 00000000 00:00 0
7fccb8089000-7fccbc000000 ---p 00000000 00:00 0
7fccc0000000-7fccc007c000 rw-p 00000000 00:00 0
7fccc007c000-7fccc4000000 ---p 00000000 00:00 0
7fccc79cb000-7fccc79cc000 ---p 00000000 00:00 0
7fccc79cc000-7fccc81cc000 rw-p 00000000 00:00 0
7fccc81cc000-7fccc81cd000 ---p 00000000 00:00 0
7fccc81cd000-7fccc89cd000 rw-p 00000000 00:00 0
7fccc89cd000-7fccc89ce000 ---p 00000000 00:00 0
7fccc89ce000-7fccc91ce000 rw-p 00000000 00:00 0
7fccc91ce000-7fccc91cf000 ---p 00000000 00:00 0
7fccc91cf000-7fccc99cf000 rw-p 00000000 00:00 0
7fccc99cf000-7fccc9ad7000 r-xp 00000000 08:05 24126366 /lib/x86_64-linux-gnu/libm-2.23.so
7fccc9ad7000-7fccc9cd6000 ---p 00108000 08:05 24126366 /lib/x86_64-linux-gnu/libm-2.23.so
7fccc9cd6000-7fccc9cd7000 r--p 00107000 08:05 24126366 /lib/x86_64-linux-gnu/libm-2.23.so
7fccc9cd7000-7fccc9cd8000 rw-p 00108000 08:05 24126366 /lib/x86_64-linux-gnu/libm-2.23.so
7fccc9cd8000-7fccc9e98000 r-xp 00000000 08:05 24126374 /lib/x86_64-linux-gnu/libc-2.23.so
7fccc9e98000-7fccca097000 ---p 001c0000 08:05 24126374 /lib/x86_64-linux-gnu/libc-2.23.so
7fccca097000-7fccca09b000 r--p 001bf000 08:05 24126374 /lib/x86_64-linux-gnu/libc-2.23.so
7fccca09b000-7fccca09d000 rw-p 001c3000 08:05 24126374 /lib/x86_64-linux-gnu/libc-2.23.so
7fccca09d000-7fccca0a1000 rw-p 00000000 00:00 0
7fccca0a1000-7fccca0b9000 r-xp 00000000 08:05 24126373 /lib/x86_64-linux-gnu/libpthread-2.23.so
7fccca0b9000-7fccca2b8000 ---p 00018000 08:05 24126373 /lib/x86_64-linux-gnu/libpthread-2.23.so
7fccca2b8000-7fccca2b9000 r--p 00017000 08:05 24126373 /lib/x86_64-linux-gnu/libpthread-2.23.so
7fccca2b9000-7fccca2ba000 rw-p 00018000 08:05 24126373 /lib/x86_64-linux-gnu/libpthread-2.23.so
7fccca2ba000-7fccca2be000 rw-p 00000000 00:00 0
7fccca2be000-7fccca2d4000 r-xp 00000000 08:05 24121519 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fccca2d4000-7fccca4d3000 ---p 00016000 08:05 24121519 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fccca4d3000-7fccca4d4000 rw-p 00015000 08:05 24121519 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fccca4d4000-7fccca646000 r-xp 00000000 08:05 6029347 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7fccca646000-7fccca846000 ---p 00172000 08:05 6029347 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7fccca846000-7fccca850000 r--p 00172000 08:05 6029347 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7fccca850000-7fccca852000 rw-p 0017c000 08:05 6029347 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7fccca852000-7fccca856000 rw-p 00000000 00:00 0
7fccca856000-7fccca87c000 r-xp 00000000 08:05 24126370 /lib/x86_64-linux-gnu/ld-2.23.so
7fcccaa44000-7fcccaa4a000 rw-p 00000000 00:00 0
7fcccaa78000-7fcccaa7b000 rw-p 00000000 00:00 0
7fcccaa7b000-7fcccaa7c000 r--p 00025000 08:05 24126370 /lib/x86_64-linux-gnu/ld-2.23.so
7fcccaa7c000-7fcccaa7d000 rw-p 00026000 08:05 24126370 /lib/x86_64-linux-gnu/ld-2.23.so
7fcccaa7d000-7fcccaa7e000 rw-p 00000000 00:00 0
7ffc6b1c8000-7ffc6b1e9000 rw-p 00000000 00:00 0 [stack]
7ffc6b1fa000-7ffc6b1fc000 r--p 00000000 00:00 0 [vvar]
7ffc6b1fc000-7ffc6b1fe000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
[1] 26639 abort (core dumped) ./test.exe
At last, when running the original code with debug mode on in CLion set up to capture Exceptions as breakpoints, it shows a Signal interruption of SIGBUS(Bus error) or a SIGSEGV(Segmentation fault) sometimes and last line of code executed before the interruption maps to the line:
int *v = (*kSubgraphs)[*bar(pos)];
in the foo function of the code presented here.
I am a little bit lost with this one. My strongest assumption is that I am using smart pointers the wrong way, despite I do not see where.
Your program has undefined behavior, because you access the object pointed to by kSubgraphs from different threads without mutual exclusion. This happens in this line of code in function foo, which is called from your thread function worker:
int *v = (*kSubgraphs)[*bar(pos)];
I can't guess why you think shared_ptr would help your case in any way. The way you do, it is totally pointless to wrap your objects in shared_ptr.
shared_ptr is used when ownership of your objects is shared from different other objects. It has nothing to do with "sharing objects between threads".

Unexplainable VIRTUAL memory behavior for multi-threading code heap allocation

I am trying to study the effect of pthread based Multi-threading code modifications on VIRTUAL memory on a 64-bit Centos based Linux system
I am attaching a spreadsheet where the observations were made on VIRTUAL MEMORY (using Linux based top command) with increasing the number of threads and each thread is allocating 1MB each.
I am pasting C++ code used for observation (below) for the reference:
From the observations made shown in the table below, for a single thread allocating 1MB data VIRTUAL memory used is 89.824MB, for 2 threads allocating 1MB each VIRTUAL memory is 165.604MB, for 3 threads allocating 1MB each VIRTUAL memory is 235MB and then onwards VIRTUAL memory increases by 1MB per thread.
Click here to view the table having observations made
To summarize, VIRTUAL memory starts with 89MB, becomes double after adding 2nd thread, again becomes almost double after adding 3rd thread, then increases by 1MB for addition of each thread, each allocating 1MB of heap.
Can anyone explain why is this behavior exhibited by the system ?
Please post if you need any other details. Looking forward for the help.
Note:
the code was compiled using g++ (g++ -o vma CODE_FILE.cpp -lpthread)
only 1MB of heap was allocated by each thread but were not populated
the generated binary size is only ~9KB (got using ls command)
#include <iostream>
#include <pthread.h>
using namespace std;
/*
NOTE: Make sure you provide NUM_THREADS in the range (1..5)
*/
#define NUM_THREADS 5
struct thread_struct
{
int id;
char *msg;
};
void *thrdFunc(void *i)
{
char *it = (char*)i;
cout << "\nthis is thread named :"<< it ;
char *mallocBlk = new char [1000000];
}
int main()
{
int rc = 0;
void *status;
char threadNames[8][8] = { "Thread1" , "Thread2", "Thread3", "Thread4", "Thread5", "Thread6", "Thread7", "Thread8"};
pthread_t threads[NUM_THREADS];
thread_struct thrStructs[NUM_THREADS];
cout << "\nIn Main, creating threads!" ;
/*
Create threads
*/
for (int i = 0; i < NUM_THREADS; i++)
{
rc = pthread_create(&threads[i], NULL, thrdFunc, &threadNames[i] );
if (rc)
{
cout << "Thrd" << i+1 << " cant be created";
}
}
/*
Wait till all the threads complete
*/
for (int i = 0; i < NUM_THREADS; i++)
{
pthread_join(threads[i], &status);
}
cout << endl;
cout << "Done! Waiting for your input!";
cin.get();
return 0;
}
Below is the memory map for 5 threads:
[rebaca#localhost stackoverflow]$ cat /proc/31528/maps
00400000-00401000 r-xp 00000000 fd:02 20451094 /home/rebaca/stackoverflow/vma
00601000-00602000 rw-p 00001000 fd:02 20451094 /home/rebaca/stackoverflow/vma
01784000-017a5000 rw-p 00000000 00:00 0 [heap]
305b400000-305b420000 r-xp 00000000 fd:00 1703944 /lib64/ld-2.12.so
305b61f000-305b620000 r--p 0001f000 fd:00 1703944 /lib64/ld-2.12.so
305b620000-305b621000 rw-p 00020000 fd:00 1703944 /lib64/ld-2.12.so
305b621000-305b622000 rw-p 00000000 00:00 0
305b800000-305b98a000 r-xp 00000000 fd:00 1703966 /lib64/libc-2.12.so
305b98a000-305bb8a000 ---p 0018a000 fd:00 1703966 /lib64/libc-2.12.so
305bb8a000-305bb8e000 r--p 0018a000 fd:00 1703966 /lib64/libc-2.12.so
305bb8e000-305bb90000 rw-p 0018e000 fd:00 1703966 /lib64/libc-2.12.so
305bb90000-305bb94000 rw-p 00000000 00:00 0
305bc00000-305bc17000 r-xp 00000000 fd:00 1703968 /lib64/libpthread-2.12.so
305bc17000-305be17000 ---p 00017000 fd:00 1703968 /lib64/libpthread-2.12.so
305be17000-305be18000 r--p 00017000 fd:00 1703968 /lib64/libpthread-2.12.so
305be18000-305be19000 rw-p 00018000 fd:00 1703968 /lib64/libpthread-2.12.so
305be19000-305be1d000 rw-p 00000000 00:00 0
305c800000-305c883000 r-xp 00000000 fd:00 1704110 /lib64/libm-2.12.so
305c883000-305ca82000 ---p 00083000 fd:00 1704110 /lib64/libm-2.12.so
305ca82000-305ca83000 r--p 00082000 fd:00 1704110 /lib64/libm-2.12.so
305ca83000-305ca84000 rw-p 00083000 fd:00 1704110 /lib64/libm-2.12.so
3066800000-3066816000 r-xp 00000000 fd:00 1704139 /lib64/libgcc_s-4.4.7-20120601.so.1
3066816000-3066a15000 ---p 00016000 fd:00 1704139 /lib64/libgcc_s-4.4.7-20120601.so.1
3066a15000-3066a16000 rw-p 00015000 fd:00 1704139 /lib64/libgcc_s-4.4.7-20120601.so.1
3066c00000-3066ce8000 r-xp 00000000 fd:00 809560 /usr/lib64/libstdc++.so.6.0.13
3066ce8000-3066ee8000 ---p 000e8000 fd:00 809560 /usr/lib64/libstdc++.so.6.0.13
3066ee8000-3066eef000 r--p 000e8000 fd:00 809560 /usr/lib64/libstdc++.so.6.0.13
3066eef000-3066ef1000 rw-p 000ef000 fd:00 809560 /usr/lib64/libstdc++.so.6.0.13
3066ef1000-3066f06000 rw-p 00000000 00:00 0
7fd3ec000000-7fd3ec115000 rw-p 00000000 00:00 0
7fd3ec115000-7fd3f0000000 ---p 00000000 00:00 0
7fd3f0000000-7fd3f0115000 rw-p 00000000 00:00 0
7fd3f0115000-7fd3f4000000 ---p 00000000 00:00 0
7fd3f4000000-7fd3f4115000 rw-p 00000000 00:00 0
7fd3f4115000-7fd3f8000000 ---p 00000000 00:00 0
7fd3f8000000-7fd3f8115000 rw-p 00000000 00:00 0
7fd3f8115000-7fd3fc000000 ---p 00000000 00:00 0
7fd3fc000000-7fd3fc115000 rw-p 00000000 00:00 0
7fd3fc115000-7fd400000000 ---p 00000000 00:00 0
7fd4032b6000-7fd4032b7000 ---p 00000000 00:00 0
7fd4032b7000-7fd403cb7000 rw-p 00000000 00:00 0
7fd403cb7000-7fd403cb8000 ---p 00000000 00:00 0
7fd403cb8000-7fd4046b8000 rw-p 00000000 00:00 0
7fd4046b8000-7fd4046b9000 ---p 00000000 00:00 0
7fd4046b9000-7fd4050b9000 rw-p 00000000 00:00 0
7fd4064bb000-7fd4064c1000 rw-p 00000000 00:00 0
7fd4064db000-7fd4064de000 rw-p 00000000 00:00 0
7ffc72456000-7ffc7246b000 rw-p 00000000 00:00 0 [stack]
7ffc72568000-7ffc72569000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]

vfork leads to a memory "free()" crash, but fork doesn't, how it happened?

I was trying to see if vfork creates a child process that shared memory with father process, like below:
#include<stdio.h>
#include<unistd.h>
int main()
{
int* pi = new int(5);
int i = 5;
pid_t id = vfork();
if (id > 0) //father
{
*pi = 4;
i = 4;
printf("father set i=%d, *pi=%d\n", i, *pi);
sleep(2);
printf("father get i=%d, *pi=%d\n", i, *pi);
delete pi;
}
else //child
{
sleep(1);
printf("child get i=%d, *pi=%d\n", i, *pi);
i = 3;
*pi = 3;
printf("child set i=%d, *pi=%d\n", i, *pi);
}
return 0;
}
I expected that the value if i and *pi are shared between father and chid process, but when I executed it:
$ g++ myvshare.cpp && ./a.out
child get i=5, *pi=5
child set i=3, *pi=3
father set i=4, *pi=4
father get i=4, *pi=4
*** Error in `./a.out': free(): invalid pointer: 0xb75f9000 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x67257)[0xb74ae257]
/lib/i386-linux-gnu/libc.so.6(+0x6d577)[0xb74b4577]
/lib/i386-linux-gnu/libc.so.6(+0x6dd31)[0xb74b4d31]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZdlPv+0x18)[0xb766bd98]
./a.out[0x8048621]
/lib/i386-linux-gnu/libc.so.6(+0x15f2d4)[0xb75a62d4]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:01 1055312 /home/x/cpp/a.out
08049000-0804a000 r--p 00000000 08:01 1055312 /home/x/cpp/a.out
0804a000-0804b000 rw-p 00001000 08:01 1055312 /home/x/cpp/a.out
0859e000-085c3000 rw-p 00000000 00:00 0 [heap]
b7200000-b7221000 rw-p 00000000 00:00 0
b7221000-b7300000 ---p 00000000 00:00 0
b73d3000-b73d5000 rw-p 00000000 00:00 0
b73d5000-b73f1000 r-xp 00000000 08:01 1181015 /lib/i386-linux-gnu/libgcc_s.so.1
b73f1000-b73f2000 rw-p 0001b000 08:01 1181015 /lib/i386-linux-gnu/libgcc_s.so.1
b73f2000-b7445000 r-xp 00000000 08:01 1181047 /lib/i386-linux-gnu/libm-2.23.so
b7445000-b7446000 r--p 00052000 08:01 1181047 /lib/i386-linux-gnu/libm-2.23.so
b7446000-b7447000 rw-p 00053000 08:01 1181047 /lib/i386-linux-gnu/libm-2.23.so
b7447000-b75f6000 r-xp 00000000 08:01 1180977 /lib/i386-linux-gnu/libc-2.23.so
b75f6000-b75f7000 ---p 001af000 08:01 1180977 /lib/i386-linux-gnu/libc-2.23.so
b75f7000-b75f9000 r--p 001af000 08:01 1180977 /lib/i386-linux-gnu/libc-2.23.so
b75f9000-b75fa000 rw-p 001b1000 08:01 1180977 /lib/i386-linux-gnu/libc-2.23.so
b75fa000-b75fd000 rw-p 00000000 00:00 0
b75fd000-b776a000 r-xp 00000000 08:01 400094 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.21
b776a000-b776b000 ---p 0016d000 08:01 400094 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.21
b776b000-b7770000 r--p 0016d000 08:01 400094 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.21
b7770000-b7771000 rw-p 00172000 08:01 400094 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.21
b7771000-b7774000 rw-p 00000000 00:00 0
b7788000-b778b000 rw-p 00000000 00:00 0
b778b000-b778d000 r--p 00000000 00:00 0 [vvar]
b778d000-b778e000 r-xp 00000000 00:00 0 [vdso]
b778e000-b77b0000 r-xp 00000000 08:01 1180949 /lib/i386-linux-gnu/ld-2.23.so
b77b0000-b77b1000 rw-p 00000000 00:00 0
b77b1000-b77b2000 r--p 00022000 08:01 1180949 /lib/i386-linux-gnu/ld-2.23.so
b77b2000-b77b3000 rw-p 00023000 08:01 1180949 /lib/i386-linux-gnu/ld-2.23.so
bf9ca000-bf9eb000 rw-p 00000000 00:00 0 [stack]
Terminated (core dupm)
What I was confused:
I expect that vfork should differ from fork in that i and *pi are shared. But still vfork seem to have COW for i and *pi, when father sets the value, child still gets old value, and vice versa.
Why there's a core dump saying "free()" failed? I tried to change vfork to fork, no such problem. How did this happen, inside libc, or glibc?
Thanks!
You wrong, with vfork(), the child doesn't share memory with the parent. The memory belongs to the parent only. vfork() differs from fork() because it doesn't copy the memory, but the behavior is undefined is you attempt to use the memory of the parent except the pid_t return by vfork(). Plus, the child must not call another function that exit() or exec() family. For example, it's undefined behavior to call printf() in the child. The child need to finish by exit() or exec().
Finally, the parent thread is blocked until the child call exit() or exec().
Like fork(), the processes created by vfork() inherits file descriptors, signal dispositions, and current working directory.
All information is in the manual of vfork.
TLDR: This is undefined behavior.

Delete an object from a vector

Step 1. Create an instance of a class
Step 2. Push this instance to a vector
Step 3. Call delete this; in a member method of an instance
Step 4. Everything is Ok
Step 5. Push something to the vector and get this
*** glibc detected *** ./app: double free or corruption (fasttop): 0x0000000001017930 ***
======= Backtrace: =========
/lib/libc.so.6(+0x71bd6)[0x7f607d60cbd6]
/lib/libc.so.6(cfree+0x6c)[0x7f607d61194c]
./app[0x40231c]
./app[0x402290]
./app[0x4053c0]
./app[0x4048fe]
./app[0x404246]
./app[0x403fe0]
./app[0x402400]
./app[0x4035cb]
./app[0x4034d3]
/lib/libpthread.so.0(+0x68ca)[0x7f607e2b78ca]
/lib/libc.so.6(clone+0x6d)[0x7f607d66a92d]
======= Memory map: ========
00400000-0040f000 r-xp 00000000 09:03 60427370 /root/AHS/app
0060e000-0060f000 rw-p 0000e000 09:03 60427370 /root/AHS/app
01017000-01038000 rw-p 00000000 00:00 0 [heap]
7f6074000000-7f6074021000 rw-p 00000000 00:00 0
7f6074021000-7f6078000000 ---p 00000000 00:00 0
7f607a595000-7f607a596000 ---p 00000000 00:00 0
7f607a596000-7f607ad96000 rw-p 00000000 00:00 0
7f607ad96000-7f607ad97000 ---p 00000000 00:00 0
7f607ad97000-7f607b597000 rw-p 00000000 00:00 0
7f607b597000-7f607b598000 ---p 00000000 00:00 0
7f607b598000-7f607bd98000 rw-p 00000000 00:00 0
7f607bd98000-7f607bd99000 ---p 00000000 00:00 0
7f607bd99000-7f607c599000 rw-p 00000000 00:00 0
7f607c599000-7f607c59a000 ---p 00000000 00:00 0
7f607c59a000-7f607cd9a000 rw-p 00000000 00:00 0
7f607cd9a000-7f607cd9b000 ---p 00000000 00:00 0
7f607cd9b000-7f607d59b000 rw-p 00000000 00:00 0
7f607d59b000-7f607d6f4000 r-xp 00000000 09:03 60425052 /lib/libc-2.11.3.so
7f607d6f4000-7f607d8f3000 ---p 00159000 09:03 60425052 /lib/libc-2.11.3.so
7f607d8f3000-7f607d8f7000 r--p 00158000 09:03 60425052 /lib/libc-2.11.3.so
7f607d8f7000-7f607d8f8000 rw-p 0015c000 09:03 60425052 /lib/libc-2.11.3.so
7f607d8f8000-7f607d8fd000 rw-p 00000000 00:00 0
7f607d8fd000-7f607d913000 r-xp 00000000 09:03 60425245 /lib/libgcc_s.so.1
7f607d913000-7f607db12000 ---p 00016000 09:03 60425245 /lib/libgcc_s.so.1
7f607db12000-7f607db13000 rw-p 00015000 09:03 60425245 /lib/libgcc_s.so.1
7f607db13000-7f607db93000 r-xp 00000000 09:03 60425438 /lib/libm-2.11.3.so
7f607db93000-7f607dd93000 ---p 00080000 09:03 60425438 /lib/libm-2.11.3.so
7f607dd93000-7f607dd94000 r--p 00080000 09:03 60425438 /lib/libm-2.11.3.so
7f607dd94000-7f607dd95000 rw-p 00081000 09:03 60425438 /lib/libm-2.11.3.so
7f607dd95000-7f607de8b000 r-xp 00000000 09:03 60032880 /usr/lib/libstdc++.so.6.0.13
7f607de8b000-7f607e08b000 ---p 000f6000 09:03 60032880 /usr/lib/libstdc++.so.6.0.13
7f607e08b000-7f607e092000 r--p 000f6000 09:03 60032880 /usr/lib/libstdc++.so.6.0.13
7f607e092000-7f607e094000 rw-p 000fd000 09:03 60032880 /usr/lib/libstdc++.so.6.0.13
7f607e094000-7f607e0a9000 rw-p 00000000 00:00 0
7f607e0a9000-7f607e0b0000 r-xp 00000000 09:03 60425177 /lib/librt-2.11.3.so
7f607e0b0000-7f607e2af000 ---p 00007000 09:03 60425177 /lib/librt-2.11.3.so
7f607e2af000-7f607e2b0000 r--p 00006000 09:03 60425177 /lib/librt-2.11.3.so
7f607e2b0000-7f607e2b1000 rw-p 00007000 09:03 60425177 /lib/librt-2.11.3.so
7f607e2b1000-7f607e2c8000 r-xp 00000000 09:03 60425205 /lib/libpthread-2.11.3.so
7f607e2c8000-7f607e4c7000 ---p 00017000 09:03 60425205 /lib/libpthread-2.11.3.so
7f607e4c7000-7f607e4c8000 r--p 00016000 09:03 60425205 /lib/libpthread-2.11.3.so
7f607e4c8000-7f607e4c9000 rw-p 00017000 09:03 60425205 /lib/libpthread-2.11.3.so
7f607e4c9000-7f607e4cd000 rw-p 00000000 00:00 0
7f607e4cd000-7f607e4eb000 r-xp 00000000 09:03 60425293 /lib/ld-2.11.3.so
7f607e6da000-7f607e6df000 rw-p 00000000 00:00 0
7f607e6e7000-7f607e6ea000 rw-p 00000000 00:00 0
7f607e6ea000-7f607e6eb000 r--p 0001d000 09:03 60425293 /lib/ld-2.11.3.so
7f607e6eb000-7f607e6ec000 rw-p 0001e000 09:03 60425293 /lib/ld-2.11.3.so
7f607e6ec000-7f607e6ed000 rw-p 00000000 00:00 0
7fff4ee3b000-7fff4ee50000 rw-p 00000000 00:00 0 [stack]
7fff4efff000-7fff4f000000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Aborted
Could someone please tell me, what is this, why this occurs and how do I fix it?
It's because you freed memory you didn't own. The vector owns the memory containing its contents.
delete this; is like taking a rental car to the salvage yard when you're done with it. Don't do that, the rental company expects it back!
Be careful of the difference between owning memory, and merely having control of it loaned to you.
Doing delete this for an object belonging to a vector you are making two big mistakes:
it's the vector that manages the memory where that instance is stored (it allocates it, deallocates it, ...), so you shouldn't mess with it. In other words, since you don't own that memory you must leave it alone.
delete is a correct match if the object was allocated with new - but the object managed by the vector is not allocated like that; instead, vector grabs a chunk of memory from the allocator (as big as it thinks it's sensible) and copies there the elements that are pushed into it using placement new; so, not only you are freeing memory that you don't own, you are also using the wrong method to free it.
If you need to remove an element from a vector, just use the vector::erase method.
If you do delete this in any method, you have to be sure that no one else calls any method ( for that matter any code) of the instance after that statement. This includes the destructor.
When you push the instance into a vector, while being destroyed, the vector calls the destructor for the instance, hence the double free
If you need a vector, you can push pointers to the instance and it would be fine.
However, as others have said DO NOT use delete this unless absolutely necessary
You would also have the problems if you just create an local instance of the class in a function. Most likely you did not see this behavior because your program finished before the scope of the local variable ended. If you tried this :
void func() {
MyClass myClass;
myClass.theBadFunc();
}
When this returns, you will have a core dump.
Does this resemble the code that you're describing?
struct MyClass {
void f() { delete this; }
};
int main() {
MyClass c;
std::vector<MyClass> v;
v.push_back(c);
c.f();
return 0;
}
The vector is irrelevant. The problem is that delete this calls the destructor for c and frees the memory where c was built. That memory is on the stack, and cannot be freed. Don't ever delete stack objects. The compiler generates code to clean them up when they go out of scope, in this case, at the end of main.

Weird stack smash error - caused by unused, uninitialized member variable

Today I had a fun bug where apparently my stack got smashed, overriding the G++ return-point canary (I think that's the protection used).
My offending class was this:
class ClientSendContext : public SendContext
{
public:
ClientSendContext(UdpClient& client);
void send(boost::asio::const_buffer buffer);
private:
boost::asio::ip::udp::endpoint endpoint;
UdpClient& client;
};
The thing was, the client variable was initialized in the initializer list, but not the endpoint (it's not used in the ClientSendContext, since it only sends to one endpoint, but no matter). The smash-stack occured once every three times I executed my test (or something like that) which is weird, since I do the exact same thing (must be thread timing issue).
However, as soon I remove the endpoint variable, it works fine! How can this be? It wasn't used in any way, g++ didn't warn me about it... Valgrind was quiet aswell.
(Could someone with high rep please edit my question and add stack-smash or something like that as a tag?)
Alright, an update with more code, posted on pastebin:
http://pastebin.com/xiWx8xjV
That should be all the methods called. The inner most send method is part of a templated class. The same send method works fine when the UdpServer uses it.. I'm just a bit stumped right now.
EDIT: Code now put directly here:
void doTest(bool& failed)
{
ReceiveHelper helper(failed);
boost::threadpool::pool pool(2);
int port = 55600;
boost::asio::io_service service;
udp::endpoint thisPoint = udp::endpoint(address::from_string("127.0.0.1"),
port);
udp::endpoint receivePoint;
udp::socket socket(service, thisPoint);
socket.async_receive_from(boost::asio::buffer(helper.buffer), receivePoint, boost::bind(&ReceiveHelper::handleReceive,
&helper, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
pool.schedule(boost::bind(&boost::asio::io_service::run, &service));
voip::network::client::UdpClient client;
client.connect(thisPoint);
client.send(1, "Hello!");
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
service.stop();
}
class ReceiveHelper {
private:
bool& failed;
public:
ReceiveHelper(bool & failed) : failed(failed), buffer()
{
}
boost::array<uint8_t, BUF_SIZE> buffer;
void handleReceive(const boost::system::error_code & error, size_t numBytes)
{
if(numBytes != 8)
return;
if(std::string((char*)buffer.c_array(), 6) != "Hello!")
return;
failed = false;
}
};
void UdpClient::send(uint8_t handler, std::string message)
{ <-------------------------------------------------------------------------------------- Canary at this point fails
ClientSendContext context(*this);
ClientConnection::send(context, handler, message);
} <-------------------------------------------------------------------------------------- Canary at this point fails
void send(SendContext & sendContext, uint8_t handler, std::string & message)
{
uint8_t *array = new uint8_t[message.size() + 2];
memcpy(array, message.c_str(), message.size());
boost::asio::mutable_buffer buffer(array, message.size() + 2);
prepareMessage(handler, buffer);
sendContext.send(buffer);
delete[] array;
}
size_t prepareMessage(uint8_t handler, boost::asio::mutable_buffer message)
{
size_t messageLength = boost::asio::buffer_size(message);
uint8_t* data = boost::asio::buffer_cast<uint8_t*>(message);
data[messageLength - 1] = network::handler;
data[messageLength - 2] = handler;
return messageLength;
}
And the error message:
*** stack smashing detected ***: ./testclient terminated
======= Backtrace: =========
/lib/libc.so.6(__fortify_fail+0x37)[0x58e9537]
/lib/libc.so.6(__fortify_fail+0x0)[0x58e9500]
./testclient(_ZN4voip7network6client9UdpClient4sendEhSs+0x85)[0x46b449]
./testclient(_ZN4voip4test6client18SuiteTestUdpClient6doTestERb+0x2dd)[0x44c7c1]
./testclient(_ZNK4voip4test6client18SuiteTestUdpClient17TestClientCanSend7RunImplEv+0x2f)[0x44c957]
./testclient(_ZN8UnitTest11ExecuteTestINS_4TestEEEvRT_RKNS_11TestDetailsE+0x9a)[0x469551]
./testclient(_ZN8UnitTest4Test3RunEv+0x23)[0x46920f]
./testclient(_ZNK8UnitTest10TestRunner7RunTestEPNS_11TestResultsEPNS_4TestEi+0x7c)[0x469b74]
./testclient(_ZNK8UnitTest10TestRunner10RunTestsIfINS_4TrueEEEiRKNS_8TestListEPKcRKT_i+0x8f)[0x469ddb]
./testclient(_ZN8UnitTest11RunAllTestsEv+0x53)[0x4697b7]
./testclient(main+0x9)[0x44ca62]
/lib/libc.so.6(__libc_start_main+0xfe)[0x5808d8e]
./testclient[0x44c429]
======= Memory map: ========
00400000-00494000 r-xp 00000000 08:05 150971 /home/max/Documents/c++proj/voip/build/testclient
00693000-00694000 r--p 00093000 08:05 150971 /home/max/Documents/c++proj/voip/build/testclient
00694000-00695000 rw-p 00094000 08:05 150971 /home/max/Documents/c++proj/voip/build/testclient
00695000-00696000 rw-p 00000000 00:00 0
04000000-04020000 r-xp 00000000 08:05 560792 /lib/ld-2.12.1.so
04020000-04022000 rw-p 00000000 00:00 0
0403f000-04045000 rw-p 00000000 00:00 0
04220000-04221000 r--p 00020000 08:05 560792 /lib/ld-2.12.1.so
04221000-04222000 rw-p 00021000 08:05 560792 /lib/ld-2.12.1.so
04222000-04223000 rw-p 00000000 00:00 0
04223000-04224000 rwxp 00000000 00:00 0
04a23000-04a24000 r-xp 00000000 08:05 145700 /usr/lib/valgrind/vgpreload_core-amd64-linux.so
04a24000-04c23000 ---p 00001000 08:05 145700 /usr/lib/valgrind/vgpreload_core-amd64-linux.so
04c23000-04c24000 r--p 00000000 08:05 145700 /usr/lib/valgrind/vgpreload_core-amd64-linux.so
04c24000-04c25000 rw-p 00001000 08:05 145700 /usr/lib/valgrind/vgpreload_core-amd64-linux.so
04c25000-04c2d000 r-xp 00000000 08:05 145715 /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so
04c2d000-04e2c000 ---p 00008000 08:05 145715 /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so
04e2c000-04e2d000 r--p 00007000 08:05 145715 /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so
04e2d000-04e2e000 rw-p 00008000 08:05 145715 /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so
04e2e000-04e46000 r-xp 00000000 08:05 557639 /lib/libpthread-2.12.1.so
04e46000-05045000 ---p 00018000 08:05 557639 /lib/libpthread-2.12.1.so
05045000-05046000 r--p 00017000 08:05 557639 /lib/libpthread-2.12.1.so
05046000-05047000 rw-p 00018000 08:05 557639 /lib/libpthread-2.12.1.so
05047000-0504b000 rw-p 00000000 00:00 0
0504b000-05133000 r-xp 00000000 08:05 656172 /usr/lib/libstdc++.so.6.0.14
05133000-05332000 ---p 000e8000 08:05 656172 /usr/lib/libstdc++.so.6.0.14
05332000-0533a000 r--p 000e7000 08:05 656172 /usr/lib/libstdc++.so.6.0.14
0533a000-0533c000 rw-p 000ef000 08:05 656172 /usr/lib/libstdc++.so.6.0.14
0533c000-05351000 rw-p 00000000 00:00 0
05351000-053d3000 r-xp 00000000 08:05 560787 /lib/libm-2.12.1.so
053d3000-055d2000 ---p 00082000 08:05 560787 /lib/libm-2.12.1.so
055d2000-055d3000 r--p 00081000 08:05 560787 /lib/libm-2.12.1.so
055d3000-055d4000 rw-p 00082000 08:05 560787 /lib/libm-2.12.1.so
055d4000-055e9000 r-xp 00000000 08:05 521495 /lib/libgcc_s.so.1
055e9000-057e8000 ---p 00015000 08:05 521495 /lib/libgcc_s.so.1
057e8000-057e9000 r--p 00014000 08:05 521495 /lib/libgcc_s.so.1
057e9000-057ea000 rw-p 00015000 08:05 521495 /lib/libgcc_s.so.1
057ea000-05964000 r-xp 00000000 08:05 557476 /lib/libc-2.12.1.so
05964000-05b63000 ---p 0017a000 08:05 557476 /lib/libc-2.12.1.so
05b63000-05b67000 r--p 00179000 08:05 557476 /lib/libc-2.12.1.so
05b67000-05b68000 rw-p 0017d000 08:05 557476 /lib/libc-2.12.1.so
05b68000-05b6d000 rw-p 00000000 00:00 0
05b6d000-05f6d000 rwxp 00000000 00:00 0
05f6d000-05f6e000 ---p 00000000 00:00 0
05f6e000-0676e000 rw-p 00000000 00:00 0
0676e000-0676f000 ---p 00000000 00:00 0
0676f000-06f6f000 rw-p 00000000 00:00 0
06f6f000-06f70000 ---p 00000000 00:00 0
06f70000-07770000 rw-p 00000000 00:00 0
07770000-07771000 ---p 00000000 00:00 0
07771000-07f71000 rw-p 00000000 00:00 0
38000000-381fc000 r-xp 00200000 08:05 145710 /usr/lib/valgrind/memcheck-amd64-linux
383fb000-383fe000 rw-p 003fb000 08:05 145710 /usr/lib/valgrind/memcheck-amd64-linux
383fe000-3927e000 rw-p 00000000 00:00 0
402001000-403272000 rwxp 00000000 00:00 0
403272000-403274000 ---p 00000000 00:00 0
403274000-403374000 rwxp 00000000 00:00 0
403374000-403376000 ---p 00000000 00:00 0
403376000-40583e000 rwxp 00000000 00:00 0
40583e000-405840000 ---p 00000000 00:00 0
405840000-405940000 rwxp 00000000 00:00 0
405940000-405942000 ---p 00000000 00:00 0
405942000-405946000 rwxp 00000000 00:00 0
405946000-405948000 ---p 00000000 00:00 0
405948000-405a48000 rwxp 00000000 00:00 0
405a48000-405a4a000 ---p 00000000 00:00 0
405a4a000-405a4e000 rwxp 00000000 00:00 0
405a4e000-405a50000 ---p 00000000 00:00 0
405a50000-405b50000 rwxp 00000000 00:00 0
405b50000-405b52000 ---p 00000000 00:00 0
405b52000-405b5a000 rwxp 00000000 00:00 0
405b5a000-405b5c000 ---p 00000000 00:00 0
405b5c000-405c5c000 rwxp 00000000 00:00 0
405c5c000-405c5e000 ---p 00000000 00:00 0
405c5e000-405c62000 rwxp 00000000 00:00 0
7feffd000-7ff001000 rwxp 00000000 00:00 0
7fffb9f36000-7fffb9f57000 rw-p 00000000 00:00 0 [stack]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
this error is (almost always) caused by appending more elements to an array/vector than said array/vector has been declared as having. therefore i would pay specific attention to all char and uint8 arrays in your code.
though the dump might make sense for someone who understands linux c++ profoundly, it makes no sense for mere mortals and debugging using it is not the fastest solution.
i like the old school approach: print flags to show up to what point your program goes without exceptions. you can usually isolate the offending array(s) this way quite quickly.
as an example, i was having the exact same problem with this code:
std::string GetTimeStringFromDump(unsigned char *bufDumpIn, int startDate) {
unsigned char bufOut[6];
for (int counter02=0;counter02<12;counter02++) {
bufOut[counter02] = bufDumpIn[counter02+startDate];
}
std::string unixTimeOut = GetTimeStringNew(bufOut);
std::cout << "UnixTimeOUT: " << unixTimeOut << std::endl;
return unixTimeOut;
}
the weirdest thing was that the error did NOT occur when i assigned a string that had 12 characters to bufOut (declared as having 6 elements), but rather after
return unixTimeOut;
nevertheless, i changed the declaration to
unsigned char bufOut[12];
and the problem was solved.