-2

Whenever I run my program I get a std::bad_alloc exception thrown which causes an abort to occur. The std::bad_alloc ONLY gets thrown when va_arg is called. The odd thing is the code that crashes was provided by the instructor. I didn't write the line that crashes. Valgrind is telling me that this is caused by new/new[]. Why is va_arg causing this? The bad_alloc ONLY occurs when it executes (which it does in other places too).

void Library::addKeywordsForItem(const Item* const item, int nKeywords, ...)
 {
     // the code in this function demonstrates how to handle a vararg in C++

     va_list         keywords;
     string          keyword = "test";
     bool            successFlag = false;
     sArray          keywordV;
     cout << "Before lookupItem\n";
     Item*           item2 = lookupItem(item);
     cout << "After lookupItem\n";

     va_start(keywords, nKeywords);
     cout << "after va_start\n";
     for (int i = 0; i < nKeywords; i++) //this code adds the items to a map of set to create a fast access structure for keyword searches
     {
         cout << "before keyword assign\n";
         keyword = va_arg(keywords, string); //Crash here
         cout << "after keyword assign\n";
         // do something with each keyword
         cout << "before HERE\n";
         keywordV.push_back(keyword); //pushes keyword onto vector
         cout << "HERE\n";
         successFlag = addToSMap(item, keyword, keywordDbase); //This function is literally a copy/paste of the code
         //originally designed for this function
     }
     va_end(keywords);

     //Sets in keywords
     item2->setKeywords(keywordV);

     if(!successFlag) //Should never execute
         cout << "This code reeks verily of wrongness.\n";
 }

The above code is called from the following instructor written line of code

library->addKeywordsForItem(item, 2, "autism", "Asperger's Syndrome");

Here are the errors I get

Valgrind

**5851**    new/new[] failed and should throw an exception, but Valgrind
**5851**    cannot throw exceptions and so is aborting instead.  Sorry.
==5851==    at 0x4C275AC: ??? (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==5851==    by 0x4C27DC6: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==5851==    by 0x4F57496: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_assign(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (basic_string.tcc:265)
==5851==    by 0x4F577E8: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (basic_string.h:1181)
==5851==    by 0x4085F8: Library::addKeywordsForItem(Item const*, int, ...) (Library.cpp:79)
==5851==    by 0x401BB5: main (Asgmt04.cpp:38)

Program

terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc Aborted

The instructor designed the loop that uses the va_args (I just filled in what it does) so I'm not sure why his code causes a crash. Is my code causing this to crash? Could someone lend some insight?

Stargateur
  • 24,473
  • 8
  • 65
  • 91
Legion Daeth
  • 329
  • 1
  • 5
  • 15

1 Answers1

4

"autism" and "Asperger's Syndrome" are const char * values, not string values, so trying to read them as strings causes undefined behaviour.

user253751
  • 57,427
  • 7
  • 48
  • 90
  • @Stargateur Would you use `const int` because it's important to know that 10 can't be modify? [sic] – user253751 Dec 08 '16 at 03:56
  • @Stargateur You're allowed to love Rust but C++ is not Rust. – user253751 Dec 08 '16 at 04:48
  • @Stargateur I want to say that different languages have different conventions. The convention in C++ is not to put const on everything possible. `std::string const &` is useful because it can refer to either a const `std::string` variable, a non-const one, or a temporary; that is a meaningful difference that justifies using `const` there. – user253751 Dec 08 '16 at 04:59
  • 1
    @Stargateur In your case the first `const` in `char const * const` makes an important difference (you're allowed to point to a const string); the second one in the variable type is not useful (it only prevents you modifying the variable, and C++ is not a language where immutability of local variables is emphasized), and the second `const` in `va_arg` is entirely superfluous. – user253751 Dec 08 '16 at 05:02