0

I have a multi-threaded application where I use a std::map for storing key-value pairs. While I keep the access to the std::map guarded with mutex locks (pthread, since not using C++11) to ensure mutual exclusion, making the key based on data is outside mutual exclusion block. This is because my key making is done locally and not with shared data. I have a small utility function mkkey that returns a string by value, defined as follows:

std::string mkkey(char *n1, char *n2, int d) {
  char buff[200];
  sprintf(buff, "%s:%s:%d", n1, n2, d);
  return buff;
}

The arguments to mkkey are not null and are valid strings, within size limits so I don't exceed buffer size. But, I get a crash, pstack core shows the following: for one thread:

 --- called from signal handler with signal 10 (SIGBUS) ---
 00271340 allocate__t24__default_alloc_template2b0i0Ui (30, 30, 10, 2, 1, 0) + a4
 0015ec84 __nw__Q2t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0_3RepUiUi (10, 20, 1, 2, 1, 1) + 14
 0015fa44 create__Q2t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0_3RepUi (19, 19, 664e10, fc27b694, ffbff790, fffc00) + 24
 0016c71c replace__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0UiUiPCcUi (fc27b888, 0, ffffffff, fc27b038, 19, 80808080) + 114
 002af8c4 assign__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCcUi (fc27b888, fc27b038, 19, fc27b051, 1, 1) + 24
 0029b380 assign__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCc (fc27b888, fc27b038, 7fffffe6, 664e10, fc27b051, 7fffffe6) + 24
 00263600 __t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCc (fc27b888, fc27b038, 7ffffc00, 664e10, fc27b895, 19) + 28
 0012caec mkKey__FRC8UserData (fc27b890, fc27b888, fc27b8a1, 0, ff000000, 80808080) + f4

and for another thread:

-----------------  lwp# 7 / thread# 7  --------------------
 0025b148 data__Q2t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0_3Rep (84f970, 4631bc, 1, 2, 1, 0) + 4
 001616c8 copy__Q2t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0_3RepUiPCcUi (84f970, 0, fbe7b0c8, 19, ffbff790, fffc00) + 24
 0016c7a8 replace__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0UiUiPCcUi (fbe7b918, 0, ffffffff, fbe7b0c8, 19, 80808080) + 1a0
 002af8c4 assign__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCcUi (fbe7b918, fbe7b0c8, 19, fbe7b0e1, 1, 1) + 24
 0029b380 assign__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCc (fbe7b918, fbe7b0c8, 7fffffe6, 664e10, fbe7b0e1, 7fffffe6) + 24
 00263600 __t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCc (fbe7b918, fbe7b0c8, 7ffffc00, 664e10, fbe7b925, 19) + 28
 0012caec mkKey__FRC8UserData (fbe7b920, fbe7b918, fbe7b931, 0, ff000000, 80808080) + f4

The thread that crashed seems to crash on a SIGBUS that usually indicates an access to an invalid address. What could go wrong? std::string being formed because of return by value from mkkey should create a std::string afresh, but it shows alloc is failing. Is it something to do with std::string? I don't see any apparent problem through while debugging with small set of data, problem comes on larger data volume. Could heap size be a problem causing failure in synamic allocation? Or is it std::string itself? I intentionally kept mkkey outside mutex locks as it is done locally and not on shared data.

Dr. Debasish Jana
  • 6,980
  • 4
  • 30
  • 69
  • "Could heap size be a problem?" - No, but stack size can (in the specific case described in this post). – barak manos Mar 07 '14 at 18:37
  • @barakmanos In that case, thread stack size may be attempted to increase, as I use the default stacksize allocated by pthread – Dr. Debasish Jana Mar 08 '14 at 01:42
  • Maybe the arguments are not as valid as you think they are? At least use `snprintf` (of course, using C++ paradigms instead would be better). Can you try to strip your program down to a minimal example that you can post in its entirety and still crashes? – M.M Mar 08 '14 at 01:58

1 Answers1

0

This is heap corruption that can have many-many reasons and it is the ugliest kind of bug that can happen in a program. It can have so many reasons that it has no point to list them. Its enough to have one tiny piece of buggy code that overwrites something else' memory for example by overindexing or by writing dangling pointers...

Here is a nice list of recommendations for debugging heap corruptions: How to debug heap corruption errors?

I myself usually debug them with special allocators and by putting (very-slow) full-memory-consistenc-check calls to specific spots in my program and this way I can sometimes do long-n search the location where my corruption happens.

Community
  • 1
  • 1
pasztorpisti
  • 3,760
  • 1
  • 16
  • 26
  • This is confined to a particular tiny module where apparent memory leakage is not there (seems on a tedious check). However, thread stack size (using default now as given by pthread) could be an issue. For debate sake, even if there is some memory overwrite caused by something, why should a fresh memory allocation fail? – Dr. Debasish Jana Mar 08 '14 at 01:45
  • @DebasishJana If you overwrite a memory area that belongs to the allocator itself (for the management of the allocated blocks) then of course the allocator will fail or crash in worst case. It can also happen that you simply run out of memory, many C++ modules silently fail in this case especially if exception handling is turned off and instead of `badalloc` exception `new` simply returns `NULL`. And it isn't just your small module that counts, every single small piece of code is suspicious that runs within the crashed process (because of using the same virtual memory address space). – pasztorpisti Mar 08 '14 at 01:52