Why this error? - Segmentation fault (core dumped) - c++

My code compiles just fine. I am running and compiling it using another server that I connect to. When I run it, I get this error that says - Segmentation fault (core dumped). It runs perfect when I compile and run it locally on my mac, just not when I use levi (the virtual machine we use to submit our files.) What do I do to not get this error message and for my code to run? Here is my code:
//
// ChaseGraingerSection6.cpp
//
// Created by Chase Grainger on 3/19/18.
//
// I typed all of this code on my own and did
// not copy any code from any outside sources.
#include <iostream>
#include <fstream>
int main() {
const int my_dimension = 10; // dimension of 'my_array'
std::string my_array[my_dimension]; // array of fixed amount of strings
int x = 0; // used to add lines of text form 'word.txt' to 'my_array'
int y = 0; // used when reversing array values
int num_of_lines = 0; // keeps track of # of lines in text file[s]
std::string text; // used when reading lines from 'word.txt'
std::string my_reversed_array[num_of_lines]; // reversed order array
std::ofstream outData; // output stream 'outData'
std::ifstream inData; // input stream 'inData'
inData.open("word.txt"); // opens input stream
while (getline(inData, text)) { // runs through each line in 'word.txt'
my_array[x] = text; // sets index value of array to line in text file
num_of_lines += 1;
x += 1;
}
inData.close(); // closes input stream
// at this point, my_array has the text needed
outData.open("chase.txt");
for (x = num_of_lines - 1; x >= 0; x--) { // assisngs values in reverse order from one array to another
my_reversed_array[x] = my_array[y];
y += 1;
}
for (x = 0; x <= num_of_lines - 1; x++) {
outData << my_reversed_array[x] << std::endl;
}
outData.close();
}

int num_of_lines = 0;
std::string my_reversed_array[num_of_lines];
This is not actually valid C++, but on a compiler supporting variable-length arrays as an extension this creates an array of zero size.
Now, whichever compiler you use, this array does not later magically change size if you change num_of_lines; that ship has sailed.
So, whenever you write to my_reversed_array, you are writing to memory that does not belong to you.
You are going to need dynamic allocation (or a std::vector) so that you can create an array with runtime bounds — and don't do it until you know what those bounds are.
To answer your next question (why this didn't crash on your Mac), you just got [un]lucky. The program is not required to crash; its behaviour is undefined. It could instead have summoned a brilliant genius to answer your question on Stack Overflow. Oh… wait… ;)

Related

For loop in C++ stops after a single iteration w/ pointer variable

So first all I'll preface this with: I just started using c++.
I have a structure that I store the pointer to in an unordered_map, setting members' values in the struct pointer as I get them through my process. Then I no longer need them in a map so I transfer then to a vector and loop through them.
Though on the second loop, it outputs my index (1) but the next statement of making a local pointer var for the struct at that index breaks it and the code terminates without any errors. since there are no errors then a try/catch doesn't give me anything either.
// Wanted to create a structure to handle the objects easier instead
// of multiple vectors for each property
struct appData {
std::string id = "";
std::string name = "";
std::string vdf_file = "";
std::string vdf_path = "";
};
// Relevant parts of my main()
int main() {
// Map that stores all the struct pointers
std::unordered_map<std::string, appData*> appDatas;
char memory[sizeof(appData)];
void* p = memory;
// New instance of appData
appData *tempAppData = new(p) appData();
tempAppData->appid = "86901";
// Add tempAppData to map with string key
appDatas["86901"] = tempAppData;
...
std::vector<appData*> unhashed_appDatas;
for (auto const& pair: appDatas) {
unhashed_appDatas.push_back(pair.second);
}
...
for (unsigned int x = 0; x < unhashed_appDatas.size(); x++) {
// Output index to see where it was messing up
std::cout << x << std::endl;
!! // This is where the issue happens on the second loop (see output)
appData *thisAppData = unhashed_appDatas[x];
std::string id = thisAppData->appid;
std::cout << id << std::endl;
/* ...
Do more stuff below
*/
}
...
return 0;
}
Terminal Output:
0 // Initial index of x
86901 // Id of first item
1 // New index of x on second loop before pointer var is created
// Nothing more is printed and execution terminates with no errors
My knowledge of c++ is pretty lacking, started it couple days ago, so the few things within my knowledge I've tried: moving the *thisAppData variable outside of the loop, using a for(var: vector) { ... }, and a while loop. I can assume that the issue lies with the pointer and the local variable when inside the loop.
Any help/input about how I could better approach this or if there's an issue with my code would be appreciated :)
Edit: Changed code to use .size() instead of sizeof() per #Jarod42 answer, though main issue persists
Edit2: Turns out it was my own mess-up, imagine that. 4Am brain wasn't working too well- posted answer regarding what I did incorrectly. Thanks to everyone who helped me
sizeof is the wrong tool here:
for (unsigned int x = 0; x < sizeof(unhashed_appDatas); x++) {
// ^^ wrong: give **static** size of the structure
// mainly 3 members (data, capacity, size), so something like `3*sizeof(void*)`
it should be
for (unsigned int x = 0; x < unhashed_appDatas.size(); x++) {
After many hours of trial and error I have determined the issue (aside from doing things in a way I should, which I've since corrected) it was something I messed up on that caused this issue.
TLDR:
Items wouldn't exist that I assumed did and tried to read files with a blank path and parse the contents that didn't exist.
Explaination:
In the first loop, the data I was getting was a list of files from a directory then parsing a json-like file that contained these file names and properties associated with them. Though, the file list contained entries that weren't in this other data file (since I had no check if they existed) so it would break there.
Additionally in the last loop I would get a member from a struct that would be the path of a file to read, but it would be blank (unset) because it didn't exist in data file so std::ifstream file(path); would break it.
I've since implemented checks for each key and value to ensure it will no longer break because of that.
Fixes:
Here are some fixes that were mentioned that I added to the code, which did help it work correctly in the end even if they weren't the main issue that I myself caused:
// Thanks to #EOF:
// No longer "using placement new on a buffer with automatic storage duration"
// (whatever that means haha) and was changed from:
char memory[sizeof(appData)];
void* p = memory;
appData *tempAppData = new(p) appData();
// To:
appData *tempAppData = new appData();
// Thanks to #Jarod42:
// Last for loop limit expression was corrected from:
for (unsigned int x = 0; x < sizeof(unhashed_appDatas); x++) {
}
// To:
for (unsigned int x = 0; x < unhashed_appDatas.size(); x++) {
}
// I am still using a map, despite comment noting to just use vectors
// (which I could have, but just would prefer using maps):
std::unordered_map<std::string, appData*> appDatas;
// Instead of doing something like this instead (would have arguably have been easier):
std::vector<std::string> dataKeys = { "1234" };
std::vector<appData*> appDatas = { ... };
auto indx = find(dataKeys.begin(), dataKeys.end(), "1234");
indx = (indx != dataKeys.end() ? indx : -1);
if (indx == -1) continue;
auto dataItem = appDatas[indx];
//
I appreciate everyone's assistance with my code

Looking for an error in a fairly basic C++ program I've written which deals with csv files

Can't seem to figure out why exactly this program won't work. It is supposed to store data from a csv file into a structure called SurnameInfo (when used with a loop that iterates through each line) but whenever I run it it gets to line 1280 of 151671 of the csv file, crashes, and gives the windows "program.exe has stopped working" popup. Anyone see anything that might cause this? Thanks!!
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdlib>
using namespace std;
const int MAXLINE = 1000;
const int MAXARRAY = 1000;
int numberOfNames;
struct SurnameInfo
{
char *name;
int count;
float pctrace[6];
};
SurnameInfo*surnames[MAXARRAY];
void processLine(char *line, int n)
{
surnames[n] = new SurnameInfo; //allocate memory
char * pch = strtok(line, ",");//start tokenizing
int len = strlen(pch); // name length
surnames[n]->name = new char[len+1]; //allocate memory
strcpy(surnames[n]->name, pch); // copy name
surnames[n]->count = atoi(strtok(NULL, ","));//get count
for (int i = 0; i < 6; i++)
{
pch = strtok(NULL, ",");
surnames[n]->pctrace[i] = pch[0] == '(' ? -1 : atof(pch);
}
}
void readLines()
{
char line[MAXLINE];
ifstream inputfile;
inputfile.open("names.csv");
if (!inputfile) return; // can't open
inputfile.getline(line, MAXLINE); //skip title
inputfile.getline(line, MAXLINE);
numberOfNames = 0;
while (!inputfile.eof()) //not end of file
{
processLine(line, numberOfNames++);
inputfile.getline(line, MAXLINE);
}
inputfile.close();
}
int main() {
readLines();
return 0;
}
I see a discrepancy in the code and the stuff that you are talking.
const int MAXARRAY = 1000; && SurnameInfo*surnames[MAXARRAY]; goes against 151671 of the csv file.
You are allocating 1000 and trying to push more to the heap unattended which means it starts eating the memory allocated to the program itself. Or it tries to access the area which it is not supposed to (may be program area of some other process is allocated), and thus pushes out a Segmentation Fault
Also, you need to have a way to destruct the Surnames that are dynamically fed.
My Suggestion :
Approach 1 : Read through the file first and get the number of lines. Allocate the respective memory to Surnames and proceed the way you are.
Though it requires one additional scan of file, but would solve your purpose. Time complexity goes very high if the file size is high.(May be you can cache stuff while reading , use vector?? (think on that))
Approach 2 : Implement a functionality similar to resize of vector.On every new addition to the Surnames, Free the previously allocated memory on heap and reallocate with the higher memory spec by deep copying and inserting new info.
Also,
surnames[n]->pctrace[i] = pch[0] == '(' ? -1 : atof(pch);
I am not very sure whether this would work correctly or not. Just for the sake of safety and more clear code, put that up in parenthesis . Something like this
surnames[n]->pctrace[i] = ((pch[0] == '(') ? -1 : atof(pch));
If this is your one of the first attempts on C++, this is nicely done. Cheers.
Hope the answer helps.

Problems with destroying an array of libtrace_out_t*

The task is to read packets from one tracer and write to many.
I use libtrace_out_t** for output tracers.
Initialization:
uint16_t size = 10;
libtrace_out_t** array = libtrace_out_t*[size];
for(uint16_t i = 0; i < size; ++i) {
array[i] = trace_create_output(uri); // created OK
trace_start_output(outTracers_[i]); // started OK
}
// writing packets
Creating, starting and writing packets using elements of tracer's array are fine.
Problems are caused by trace_destroy_output() when I destroy output tracers in loop:
for(uint16_t i = 0; i < size; ++i)
{
if(outTracers_[i])
trace_destroy_output(outTracers_[i]);
}
On the first iteration output tracer is destroying fine.
But on the second it fails with Segmentation fault in
pcap_close(pcap_t* p)
because pointer p has value 0x0.
Can someone explain me why this thing happens or how to destroy it properly?
From the code that you have posted, it looks like you are creating 10 output traces all using the same URI. So, essentially, you've created 10 output files all with the same filename which probably isn't what you intended.
When it comes time to destroy the output traces, the first destroy closes the file matching the name you provided and sets the reference to that file to be NULL. Because the reference is now NULL, any subsequent attempts to destroy that file will cause a segmentation fault.
Make sure you change your URI for each new output trace you create and you should fix the problem.
Example:
/* I prefer pcapfile: over pcap: */
const char *base="pcapfile:output";
uint16_t size = 10;
libtrace_out_t* array[size];
for (uint16_t i = 0; i < size; ++i) {
char myuri[1024];
/* First output file will be called output-1.pcap
* Second output file will be called output-2.pcap
* And so on...
*/
snprintf(myuri, 1023, "%s-%u.pcap", base, i);
array[i] = trace_create_output(uri);
/* TODO Check for errors here */
if (trace_start_output(array[i])) {
/* TODO Handle error case */
}
}
One other hint: libtrace already includes a tool called tracesplit which takes an input source and splits the packets into multiple output traces based on certain criteria (e.g. number of packets, size of output file, time interval). This tool may already do what you want without having to write code or at least it will act as a good example when writing your own code.
I think you have an out of bounds access in your code
uint16_t size = 5; /// number of tracers
for(uint16_t i = 0; i != size; ++i)
{
if(outTracers_[i])
trace_destroy_output(outTracers_[i]);
}
translates to
for(uint16_t i = 0; i <= 5; ++i)
{
...
}
And outTracers_[5] is not a valid element in your array

Seg Fault resulting from push_back call on vector (threads linux)

So what I'm trying to do is write a program that creates a series of child threads that take the arguments using the pthread_create method and uses the parameter passed in to do more manipulation and so on. The parameter I'm trying to pass in is a vector argument called reduce_args_. this is the header information for the struct ReduceVector.
typedef vector<string> StringVector;
// a data structure to maintain info for the reduce task
struct ReduceArg
{
ReduceArg (void); // constructor
~ReduceArg (void); // destructor
pthread_t tid; // thread id of the reduce thread
StringVector files_to_reduce; // set of files for reduce task
};
// more typedefs
typedef vector<ReduceArg *> ReduceVector;
now the issues comes when I call push_back here:
for(int i = 0; i < num_reduce_threads_ ; i++){
reduce_args_.push_back(phold);
int count = 0;
for(ShuffleSet::iterator it = shuffle_set_.begin(); it!=shuffle_set_.end(); ++it){
string line = *it;
string space = " ";
string file = line.substr(0, line.find(space)) + ".txt";
if (count < num_reduce_threads_){
cout << reduce_args_[i+1];
(reduce_args_[i+1] -> files_to_reduce)[count] = file;
//(reduce_args_[i+1] -> files_to_reduce).push_back(file);
}
count++;
//cout << ((reduce_args_.back())->files_to_reduce).back()<< endl;
}
}
both of those push_back methods cause a seg fault. the shuffle set is just a set and is outputting strings. and as noted in the .h file, the files_to_reduce is a string vector. So what I'm trying to do is access the files_to_reduce and push_back a string onto it, but each time I get a seg fault. The reduce_args_ obj is declared as below:
ReduceArg* plhold;
reduce_args_.push_back(plhold);
((reduce_args_.back()) -> files_to_reduce).push_back("hello");
for (int i = 0; i < this->num_reduce_threads_; ++i) {
// create a placeholder reduce argument and store it in our vector
(reduce_args_.push_back(plhold));
}
thanks for the help!!
This:
ReduceArg* plhold;
reduce_args_.push_back(plhold);
Unless you've hidden some important code, you're pushing an uninitialised pointer, so the next line will cause chaos.
Possibly you meant this?
ReduceArg* plhold(new ReduceArg);
..but I suspect you haven't properly thought about the object lifetimes and ownership of the object whose address you are storing in the vector.
In general, avoid pointers unless you know exactly what you're doing, and why. The code as posted doesn't need them, and I would recommend you just use something like this:
typedef vector<ReduceArg> ReduceVector;
....
reduce_args_.push_back(ReduceArg());
reduce_args_.back().files_to_reduce.push_back("hello");
for (int i = 0; i < num_reduce_threads_; ++i) {
// create a placeholder reduce argument and store it in our vector
(reduce_args_.push_back(ReduceArg());
}

Different outputs after debugging and compiling C++ programs

I'm running CodeBlocks on the MingW compiler in an XP virtual machine. I wrote in some simple code, accessible at cl1p , which answers the algorithm question at CodeChef (Well it only answers it partly, as I have not yet included the loop for multiple test cases.
However, my problem is, that while running it in debug mode, it gives the correct output of 5, for the input:
3
1
2 1
1 2 3
However, when I build and run it, it gives the absurd, huge output 131078, what seems like garbage to me. I do not understand how the hell this is happening, but am guessing it's something to do with the dynamic memory allocation. What's the problem here, and how can I fix it? I even ran it through the online compiler at BotSkool, and it worked fine. After adding the loop for test cases, the code even worked correctly on CodeChef!
#include <iostream>
using namespace std;
int main()
{
// Take In number of rows
int numofrows;
cin >> numofrows;
// Input Only item in first row
int * prevrow;
prevrow = new int[1];
cin >> prevrow[0];
// For every other row
for (int currownum = 1; currownum < numofrows; currownum++)
{
// Declare an array for that row's max values
int * currow;
currow = new int[currownum+1];
int curnum;
cin >> curnum;
// If its the first element, max is prevmax + current input
currow[0] = prevrow[0] + curnum;
// for every element
int i = 1;
for (; i <= currownum; i++)
{
cin >> curnum;
// if its not the first element, check whether prevmax or prev-1max is greater. Add to current input
int max = (prevrow[i] > prevrow[i-1]) ? prevrow[i] : prevrow[i-1];
// save as currmax.
currow[i] = max + curnum;
}
// save entire array in prev
prevrow = new int[i+1];
prevrow = currow;
}
// get highest element of array
int ans = 0;
for (int j=0; j<numofrows; j++)
{
if (prevrow[j] > ans)
{
ans = prevrow[j];
}
}
cout << ans;
}
Run the code through Valgrind on a Linux machine and you'll be amazed at how many places your code is leaking memory.
If you are taking the hard road of managing your memory, do it well and 'delete' all the new-allocated memory before allocating more.
If, on the other hand, you prefer the easy road, use a std::vector and forget about memory management.
For one thing, this:
//save entire array in prev
prevrow = new int [i+1];
prevrow = currow;
copies the pointer, not the whole array.
In your loop, you have this line
int max = (prevrow[i]>prevrow[i-1])?prevrow[i]:prevrow[i-1];
On the first iteration of the main loop, when currownum == 1, the loop containing this line will be entered, as i is initialized to 1. But on the first iteration, prevrow only has one element and this line tries to access prevrow[1]. In a debug build, the memory simply gets initialized to zero, but in a normal build, you get some garbage value that just happened to be in the memory, leading to the result you see.
Pretty much always, when you get garbage values in a normal build, but everything is fine in a debug build, you are accessing some uninitialized memory.
Also, your program is leaking memory like crazy. For instance, you don't need to assign any result of new inside the loop to prevrow because right after that you change prevrow to point to another block of allocated memory. Also, you should call delete for any memory that you are no longer using.