ostringstream SOMETIMES causes a crash - c++

So I wrote an implementation of an ArrayList over the summer, and I have a toString method within which I use an ostringstream object to tack on strings and then output them.
the method is below:
template<class T>
std::string ArrayList<T>::toString() {
std::ostringstream streamOut;
streamOut << "(";
for (int i = 0; i < size; i++) {
streamOut << array[i];
if (i != (size - 1)) {
streamOut << ", ";
}
}
streamOut << ")\n";
std::string returnString = streamOut.str();
return returnString;
}
The problem is that when I run this program it sometimes crashes on the line in the above method:
streamOut << "(";
I tried adding a flush statement at the end but that didn't do the trick...I really have no idea what could be wrong here.
I think this issue may be related but I can't be sure....
https://stackoverflow.com/questions/8250851/big-ostringstream-causes-application-crash
EDIT:
I forgot to mention, that I am using eclipse for development, and I have been unable to get a crash of the program to occur when I run it in eclipse. It's only when I run the exe generated via windows or the command line that it crashes

I think it crashed because somewhere before this method incorrectly free the memory.

Related

How to print a two dimensional array in cocos2dx

I have a two-dimensional array that I want to print to the output of visual studio to see the result each time I modify that, I tried using std::cout and it does not work, if I use CCLOG the function will automatically write a newline each time it's called that and it's not a two-dimensional array pretty solution, I also tried CClog not sure what's the difference with CCLOG but this time it even give a compiling error :(
like I want the output be:
1,2,4,4,5
5,5,4,3,0
4,4,4,4,7
6,6,6,6,6
Here is what I tried:
void HelloWorld::PrintBrickArray() {
CCLOG("will print brick array");
std::cout << "===Begin of Array ====" << std::endl;
for (int i = 0; i < MATRIX_Y; i++) {
for (int j = 0; j < MATRIX_X; j++) {
//CCLog("%d", this->brickArray[i][j]);
std::cout << this->brickArray[i][j] << ' ';
}
std::cout << std::endl;
}
std::cout << "*****END OF Array *****" << std::endl;
std::cout.flush();
}
How to do that with coco2dx?
CCLOG or cocos2d::log uses the Visual Studio's Debug windows, which is different to write to console where std::cout works.
Therefore, there are two ways to get rid of your problem: writing to console using std::cout or writing to output windows using different methods than CCLOG
First choice, you have to change your project type from Win32 Application Project to Win32 Console Project. This is kind of going around with Visual Studio stuffs, and in most cases, your project is created automatically via cocos2d's console. You can see this post. I'm not recommend this way IMO.
Second choice, use your own code to write to output which discussed here.
There is another way that you can use std::string and std::ostringstream to "print" your variables to buffer, and then just print your string to output windows via CCLOG
CCLOG is a little bit wrapping the code to make it convenience where we log resources checking, errors, file processing, etc which usually occur when run time. If not in those cases, you should probably set break points to view what the values are instead.
Edited: Since you chose the second approach, I would recommend using std::ostringstream than sprintf, and using CCLog instead of OutputDebugString (because you just print it out and independent OS, no need extra arguments)
Here is an example code:
#include <vector>
#include <sstream> // for ostringstream
#include <Windows.h> // for OutputDebugStringA
using namespace std;
int main(void)
{
// Assuming that you have this 2d array
vector< vector<int> > arr2d;
arr2d.push_back({ 2,2,1,4 });
arr2d.push_back({ 2,4,1,5 });
arr2d.push_back({ 2,4,7,2 });
arr2d.push_back({ 3,2,0,1 });
ostringstream buffer;
for (int i = 0; i < arr2d.size(); i++)
{
for (int j = 0; j < arr2d[i].size(); j++)
{
buffer << arr2d[i][j] << '\t';
}
buffer << endl;
}
// Assuming that you use OutputDebugString for windows-only
//OutputDebugStringA(buffer.str().c_str());
// I recommend this
cocos2d::log(buffer.str().c_str());
return 0;
}
Now, buffer works nearly the same as cout, it just "print" to buffer instead, then you can get one using str(). But cocos2d::log use C-style string, so c_str() will get rid of the problem
See more about std::ostringstream here

Moxa embedded programming: weird error

I am currently working on a project where we are using a Moxa EM-1220-LX running linux, programming it using C++. During the development I have come across a bizzare error.
I have the following code:
std::string vector_to_string(std::vector<int> vec) {
std::stringstream ss;
for (int i = 0; i < vec.size(); i++) {
ss << vec[i] << ".";
}
return ss.str();
}
void print_string(std::string text) {
std::cout << text << "\n";
}
std::vector<int> local_vector;
local_vector.push_back(123);
local_vector.push_back(456);
local_vector.push_back(789);
//Case 1: Prints 456.789.
print_string(vector_to_string(local_vector));
//Case 2: Prints 123.456.789.
std::string temp = vector_to_string(local_vector);
print_string(temp);
Anyone have any idea why the first entry in the vector gets removed in Case 1, but works fine in Case 2?
I cannot reproduce your issue by compiling the code from the question. Perphaps you have a bug somewhere else in the code which causes heap/stack corruption.
Old answer: you seem to have a bug here:
for (int i = 0; i < vec.size(); i++) {
ss << vec << ".";
}
Shouldn't the middle line read ss << vec[i] << ".";? This may well explain why your vector is not printed properly.

C++ Writing to file or console by argument

Ok, so I would like to do something I myself do find rather interseting .. I want an optional argument in my function and this argument would do two things;
1. Decide whether the text is being printed to the console or to a file
2. Print it to a file if that's the case, otherwise to console
I want it to be in the same function because I want very efficient code.
This is how I tried to solve it but obviously doesn't work
void Maze::Print_maze(std::string file = "no!ne") const{
if (file != "no!ne")
std::ofstream outfile(file);
for (int i = 0; i < Map.size(); i++)
{
for (int j = 0; j < Map[i].size(); j++)
{
if (file == "no!ne")
std::cout << Map[i][j];
else
outfile << Map[i][j];
}
if (file == "no!ne")
std::cout << std::endl;
else
outfile << std::endl;
}
}
For the curious ones ..
The code is from a maze project I'm working on, I'm generating a randomized maze, solving it and there's also the possibility of reading a maze from a file then solving it.
Now all that remains is to print it to a file. But as said, rather than making two functions, I'd like to merge my normal print to console with print to a file. I'm just wondering how .. Is it possible?
My "Map[][]" is a vector <vector<char> >
void Maze::Print_maze(std::ostream& s = std::cout)
Then just pass any stream you want to write to.
The best approach is to have an std::ostream* that points to an std::ofstream, if you want to write to a file, or std::cout if you want to write to the console.
std::ostream* outputTarget = &std::cout;
void output(const std::string& message)
{
*outputTarget << message;
}
void useFileOutput()
{
static std::ofstream outFile;
if (!outFile.is_open())
outFile.open("log.txt");
outputTarget = &outFile;
}
void useCout()
{
outputTarget = &std::cout;
}
In you situation I would make 3 function, two with the signatures you want to disambiguate and one that actually does the work. This way you get the unification of having one function do the work and the cleanliness of two functions:
public:
void Maze::Print_maze(std::ostream& OutputTarget){
for (int i = 0; i < Map.size(); i++)
{
for (int j = 0; j < Map[i].size(); j++)
{
OutputTarget << Map[i][j];
}
OutputTarget << std::endl;
}
}
void Maze::Print_maze() const{
Print_maze(std::cout);
}
void Maze::Print_maze(std::string file) const{
std::ofstream Output_file(file.c_str());
Print_Maze(Output_file);
Output_file.close();
}
Passing around references to the base types allows your maze output logic to ignore the actual output type and focus on rendering the maze.
This in some obtuse sense that is unlikely to matter would also be more performant because you would not need to make a series of string comparisons.
More importantly this version with the presentation and business(maze rendering is now a business) logic separate is simpler, therefor easier to read and less bug prone.
Thanks guys, I read your replies, I'm thankful for all the good comments and efforts you put to help me. I came to a solution and I believe this is the best solution to my problem that I can come up with.
I also added a bit of error-management
void Maze::Print_maze(std::string file) const{
std::ofstream outfile(file);
// if file is open, write to file otherwise write to console
std::ostream &out= (!outfile.is_open()? std::cout : outfile);
// Check if file failed to open
if(file != "" && (!outfile.is_open()))
std::cerr << "File failed to open." << std::endl;
for (int i = 0; i < Map.size(); i++)
{
for (int j = 0; j < Map[i].size(); j++)
{
out << Map[i][j];
}
out << std::endl;
}
if(outfile.is_open())
outfile.close();
}
Edit:
Forgot to mention this ..
My Maze.h file with my class consists of this function declaration:
void Print_maze(std::string file = "") const;

c++ map<string,string>::find seems to return garbage iterator

map<string,string>::find seems to be returning garbage iterator, since i can access neither my_it->first nor second (NB: my_it != my_map.end() is verified). VC2010 reports a debug error, and looking deeper reveals
my_it is (Bad Ptr, Bad Ptr).
The 'offending' map is a class attribute, _match, shown below in context:
class NicePCREMatch
{
private:
map<string, string, less<string> > _match;
public:
void addGroup(const string& group_name, const string& value);
string group(const string& group_name);
};
Here is the code that returns elements by key (the commented-out code works fine):
string NicePCREMatch::group(const string& group_name)
{
/*for (map<string, string, less<string> >::iterator j = _match.begin(); j != _match.end(); j++)
{
if(!strcmp(j->first.c_str(), group_name.c_str()))
{
return j->second;
}
}
throw runtime_error("runtime_error: no such group");*/
map<string, string, less<string> >::iterator i = _match.find(group_name);
if (i == _match.end())
{
throw runtime_error("runtime_error: no such group");
}
return i->second;
}
And Here is the code that inserts new elements in the map:
void NicePCREMatch::addGroup(const string& group_name, const string& value)
{
_match.insert(pair<string, string>(group_name, value));
}
Another class uses NicePCREMatch as follows:
template<class Match_t>
vector<Match_t> NicePCRE<Match_t>::match(const string& buf)
{
[snip]
Match_t m;
[snip]
m.addGroup(std::string((const char *)tabptr + 2, name_entry_size - 3), \
buf.substr(ovector[2*n], ovector[2*n+1] - ovector[2*n]));
[snip]
addMatch(m);
[snip]
return _matches;
}
Where,
template<class Match_t>
void NicePCRE<Match_t>::addMatch(const Match_t& m)
{
_matches.push_back(m);
}
Finally, client code uses NicePCRE class as follows:
void test_NicePCRE_email_match(void)
{
NicePCRE<> npcre;
npcre.compile("(?P<username>[a-zA-Z]+?)(?:%40|#)(?P<domain>[a-zA-Z]+\.[a-zA-Z]{2,6})");
vector<NicePCREMatch> matches = npcre.match("toto#yahoo.com");
assert(!matches.empty());
assert(!strcmp(matches.begin()->group("username").c_str(), "toto"));
cout << matches.begin()->group("domain").c_str() << endl;
assert(!strcmp(matches.begin()->group("domain").c_str(), "yahoo.com"));
}
BTW, this --is pretty much-- my main (the oddest TDD ever :) ):
int main()
{
int test_cnt = 0;
cout << "Running test #" << test_cnt << " .." << endl;
test_NicePCRE_email_match();
cout << "OK." << endl << endl;
test_cnt++;
SleepEx(5000, 1);
return 0;
}
What am I doing wrong here?
EDIT:
The following modification (compare with the version above) solved my problem. Viz,
void NicePCREMatch::addGroup(const string& group_name, const string& value)
{
_match.insert(pair<string, string>(group_name.c_str(), value.c_str()));
}
Client code (slightly modified) now looks like this:
void test_NicePCRE_email_match(void)
{
NicePCRE<> npcre;
npcre.compile("(?P<username>[a-zA-Z]+?)(?:%40|#)(?P<domain>[a-zA-Z]+\.[a-zA-Z]{2,6})");
vector<NicePCREMatch> matches = npcre.match("toto#yahoo.com");
assert(!matches.empty());
try
{
assert(!strcmp(matches.begin()->group("username").c_str(), "toto"));
assert(!strcmp(matches.begin()->group("domain").c_str(), "yahoo.com"));
cout << "username = " << matches.begin()->group("username") << endl;
cout << "domain = " << matches.begin()->group("domain") << endl;
}
catch (const runtime_error& e)
{
cout << "Caught: " << e.what() << endl;
assert(0x0);
}
}
This is quite bizarre. Can someone please explain. However, I consider my problem solved already.
Thanks every one.
Your issue is here
if (i == _match.end())
{
throw runtime_error("runtime_error: no such group");
}
return i->second;
Your find failed for some reason. I can't say why because I don't have the full code. But, after the failure, you are throwing an error, but there is nobody to catch outside. Please add a try catch at the point where you call the method group() and implement the logic if the match is not found.
I tried with your sample snippets (+ some changes to get the stuff compiled) and it looks like visual studio continues with the next line in the function even after a throw statement. I don't know the theory behind it. I was bit surprised at seeing such a behavior.
[To make sure that your class structure is not causing the problem, I tried with a simple global method and even the method also gave me the same behavior. If there are somebody who can explain this please feel free.]
This might be caused by three things - either you modify the map in some way after the execution of find or you have a memory coruption somewhere in your program or the debugger is simply not showing the correct values for the iterator.
Try using debug output - if the code crashes when you try to output the values, then probably the iterator is really broken.
Also make sure you do not modify the map after the execution of find. If you do, this may make the iterator invalid and so you need to move the find call immedietly before using the iterator.
If both of the above options don't help you probably have memory corruption somewhere and you need to find it. Maybe use valgrind for that. Please note this should be your last resort only when the two other options are proved impossible.

Unexplained out_of_range in string::substr

I have been getting a really annoying error about an std::out_of_range when calling substr. The exact error is
terminate called after throwing an
instance of 'std::out_of_range'
what(): basic_string::substr
I'm absolutely sure that tmp_request has a length greater then 1. No matter what I pass to substr—1, 2, or bodypos—it always throws that error. I'm using g++ on Unix.
Only interesting thing I can include is the string has multiple "\r\n", including one "\r\n\r\n".
In one cpp file:
std::string tmp_request, outRequest;
tmp_request = SS_Twitter->readData();
outRequest = SS_Twitter->parse(tmp_request);
In another:
std::string parse(const std::string &request)
{
std::map<std::string,std::string> keyval;
std::string outRequest;
if(request[0]=='P')
{
if(request.find("register")!=std::string::npos)
{ //we have a register request
size_t bodypos = request.find("username");
if(bodypos==std::string::npos)
{
HttpError(400,"Malformed HTTP POST request. Could not find key username.",request);
}
else
{
std::string body = request.substr(bodypos);
StringExplode(body,"&", "=",keyval);
outRequest = "doing stuff";
}
}
Update:
std::string request2("P\r\nregister\r\nusername=hello\r\n\r\n");
std::string body = request2.substr(4);
That throws the same error. Now I know this is perfectly valid and correct code, but it's still throwing the error.
//removed source link
I modified your sample slightly to decrease amount of indentation used.
There are 5 "test cases" and none causes any problem. Could you please provide a sample request to reproduce the problem you're having.
EDIT: Forgot to mention: if this sample as it is (with commented-out bits) doesn't produce that error, your best bet is that you have a bug in your StringExplode function. You could post its source, to get a more helpful advice.
EDIT2:
In your StringExplode, change results[tmpKey] = tmpKey.substr(found+1); to results[tmpKey] = tmpResult[i].substr(found+1);. Change int found to size_t found, and remove all of if (found > 0), that will fix your mysterious out_of_range. You were substr-ing a wrong string. Just in case, here's the code with a fix:
void StringExplode(std::string str, std::string objseparator, std::string keyseperator,
std::map <std::string, std::string> &results)
{
size_t found;
std::vector<std::string> tmpResult;
found = str.find_first_of(objseparator);
while(found != std::string::npos)
{
tmpResult.push_back(str.substr(0,found));
str = str.substr(found+1);
found = str.find_first_of(objseparator);
}
if(str.length() > 0)
{
tmpResult.push_back(str);
}
for(size_t i = 0; i < tmpResult.size(); i++)
{
found = tmpResult[i].find_first_of(keyseperator);
while(found != std::string::npos)
{
std::string tmpKey = tmpResult[i].substr(0, found);
results[tmpKey] = tmpResult[i].substr(found+1);
found = tmpResult[i].find_first_of(keyseperator, found + results[tmpKey].size());
}
}
}
Initial test code:
#include <iostream>
#include <map>
#include <string>
std::string parse(const std::string &request)
{
std::map<std::string,std::string> keyval;
std::string outRequest;
if(request[0] != 'P')
return outRequest;
if(request.find("register") == std::string::npos)
return outRequest;
//we have a register request
size_t bodypos = request.find("username");
if(bodypos==std::string::npos)
{
// HttpError(400,"Malformed HTTP POST request. Could not find key username.",request);
// you said HttpError returns, so here's a return
return outRequest;
}
std::string body = request.substr(bodypos);
// StringExplode(body,"&", "=",keyval);
outRequest = "doing stuff";
return outRequest;
}
int main()
{
std::string request("P\r\nregister\r\nusername=hello\r\n\r\n");
std::cout << "[" << parse(request) << "]\n";
request = "Pregisternusername=hello\r\n\r\n";
std::cout << "[" << parse(request) << "]\n";
request = "Pregisternusername=hello";
std::cout << "[" << parse(request) << "]\n";
request = "registernusername=hello";
std::cout << "[" << parse(request) << "]\n";
request = "";
std::cout << "[" << parse(request) << "]\n";
return 0;
}
This outputs, predictably:
[doing stuff]
[doing stuff]
[doing stuff]
[]
[]
Are you sure that it's failing on that substr and not on a substr call within the HttpError or StringExplode functions? If you haven't already, you should run this through a debugger so that you can see exactly where it's throwing the exception. Alternatively, you could add a:
std::cout << "calling substr" << std::endl;
line immediately before you call substr, and a similar line immediately afterwards, so that it would look like:
std::cout << "calling substr" << std::endl;
std::string body = request.substr(bodypos);
std::cout << "finished calling substr" << std::endl;
StringExplode(body,"&", "=",keyval);
outRequest = "doing stuff";
If that substr really is throwing the exception, then you'll know because the program will print "calling substr" without a matching "finished calling substr". If it prints the pair of debug messages, though, or none at all, then something else is throwing the exception.
One fairly obvious thing wrong with your code:
int k = read(ns, buf, sizeof(buf)-1);
buf[k] = '\0';
You are not checking that read() succeeded - it returns -1 on failure which will cause all sorts of memory corruption problems if it occurs.
Also:
char * buf2 = const_cast<char *>(reply.c_str());
write(ns,buf2,sizeof(buf2));
You are taking the size of the pointer - you want the length of the output string:
write(ns, buf2, reply.size() );
And you should once again test that write succeeded and that it wrote as many bytes as you requested, though this shouldn't directly cause the substr() error.
Looks like you need an else after
if(bodypos==std::string::npos)
{
HttpError(...);
}
otherwise you are calling substr with bodypos = npos
You might consider using the (unsigned) type std::string::size_type instead of int.
Why are you casting the result of find to an int here:
int(request.find("register"))!=std::string::npos