this is the code which i am trying to run.The compiler shows some warning that the variable 'p' may be possible to be used uninitialized.
And ..on running it has a problem ..i will show..below.
please correct me and explain .
Thank you.
execution of code
*
code
that error is that..the first two elements of the character array being output are somewhat messed up!!!*
#include<bits/stdc++.h>
using namespace std;
class file{
public:int a;
char* name;
public:
file(int x,char* b):a(x){name=b;}
void printfile(){cout<<a<<" "<<name<<endl;}
};
int main(){
char *p;
int x=10;
cout<<"enter a name"<<endl;
cin>>p;
file k(x,p);
ofstream f("file",ios::out|ios::binary);
f.write((char*)&k,sizeof(class file));
f.close();
ifstream of("file",ios::in|ios::binary);
file o(0,'\0');
of.read((char*)&o,sizeof(class file));
o.printfile();
of.close();
return 1;
}
You have p as some pointer. Who is going to allocate the memory that pointer points to?
In C it is almost always the responsibility of the caller to allocate any buffers before the call.
If you don't want to, then use a std::string instead.
First of all I would advise you to read some basic manual about the c++ pointers and memory handling so you will better understand the source of the problem.
There are two major problems in your code.
The first is that you are creating a pointer which is not connected to any allocated memory. In simple words you are asking to access a memory address without asking the system to reserve it for you.
Additionally, in that memory location there can already be stored any bit configuration. The initialization of a variable is the task of giving a chunk of memory some data which have a meaningful interpretation. I'm not even sure what the in-stream operator of char* is supposed to do in this particular case. He is probably appending your characters after the last one which is not a 0 or an end of line.
Related
I am working on this assignment and have encountered a problem. At one point, I have to ask the user for two input commands to be used later and I want them put in a char array. I then want to put the input they have into char* but I end up with a Segmentation fault
Here is a small part of my code that shows where I'm having problems:
#include <iostream>
#include <cstring>
using namespace std;
int main(){
char firstAns[80];
char * command1[5];
int ansLen;
//Ask for command
cout << "Please enter your first command(incl. args) or quit: ";
cin >> firstAns;
ansLen = strlen(firstAns);
for(int i=0; i < ansLen; i++){
strcpy(command1[i], firstAns);
}
The program that I ran this from compiles just fine but I have narrowed the segmentation fault to this part of the program and could use some help as a novice programmer :)
You have an array of char* called command. But you haven't allocated any memory for the pointers in the array, or even set them to null. SO they're random values, pointing to random memory locations. Strcpy is then overwriting those random locations, causing a seg fault. You need to allocate memory for those pointers by command[i]=new char[80] on all 5 rows first.
char * command1[5];
This is an array of char*s. However, it is uninitialized - the values can be any value, and as such they point to random, meaningless places in memory.
You then later use the uninitialized command1[i] in strcpy(command1[i], firstAns);. Essentially, what you have done is taken a random place in memory and tried to copy firstAns to it. No wonder your program crashes!
Before using a pointer, you have to initialize it to some value. If you need storage in memory, use malloc() to return storage of the correct size (sizeof(datatype)*length +1 if it is a string) and remember to free() the pointer returned from it when you're done with it.
Read more: http://www.cplusplus.com/reference/cstdlib/malloc/
(Gabe Sechan's solution is also valid. new and malloc are the C++ and C ways of allocating memory)
Additional Problem is here:
ansLen = strlen(firstAns);
for(int i=0; i < ansLen; i++){
strcpy(command1[i], firstAns);
}
ansLen is the length of firstAns, it may be possible that it is longer than 5. In this case,
if you try to access command1[i], you are going to access memory that out of bounds, results in segfault.
Meanwhile, you are using unitialized command1 as pointed out by Patashu and Gabe.
Is it possible to mimic the behavior of dynamic allocation using the following code. For example we do not know the exact number of the integer that are stored in a file and we are going to read the file and then store it in an array called Hello.
int x;
int n=0;
ifstream input("a.dat");
while (!input.eof())
{
input >> x;
n++;
}
input.close();
int Hello[n];
cout << "n= " << n << endl;
int i=0;
while (!input.eof())
{
input >> Hello[i];
i++;
}
Is it possible to mimic the behavior of dynamic allocation using the
following code.
No, the major difference is that the array in your program is stored on stack, whereas all dynamic memory allocations takes place on heap.
What you are exactly doing, in your code is using the VLA feature of C99 standard of C in C++. Compiling with the -pedantic option in g++ compiler will reveal this. Since it is not directly supported by c++, and it is a implementation-specific language extension, its not such a good idea to use it, if you aim to write portable code.
VLA's use alloca() , to allocate memory on stack at runtime, and the disadvantages of such a tecnnique are discussed here.
Further more, VLA's allocate memory on stack during runtime, and if the value exceeds the range, the program simply crashes, while it is ok to quickly create a few bytes of array using VLA's , creating uncertain amounts of large memory may not be safe, and it is best to handle it using dynamic memory allocation.
int Hello[n];
is NOT dynamic allocation. It is required that n is a compile time constant if you want to declare Hello in this way.
try:
int* Hello = new int[n];
and don't forget to release the memory when you are done using it:
delete[] Hello;
This is allowed as an extension by some compilers, but is not strictly part of C++.
int Hello[n];
As an alternative, you can allocate the memory yourself:
int* Hello = new int[n];
And free it yourself also:
delete[] Hello;
But you can avoid manual memory management by usng std::vector from <vector>. One of its constructors accepts an initial size:
vector<int> Hello(n); // Vector with n elements, all initially 0.
You can also set an initial capacity without resizing, to do the allocation once:
vector<int> Hello; // Empty vector.
Hello.reserve(n); // Allocate space for n elements; size() is still 0.
Then read into an int and use push_back to insert values:
int value;
while (input >> value)
Hello.push_back(value);
Note the use of input >> value as the loop condition—this reads as long as reads are successful. eof() returns true only when the last read operation failed due to unexpected end of file, which is unlikely to be exactly what you want.
For a start the second
while (!input.eof())
Will always fail. That terminated the first one and then you set about closing that input stream!
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why don’t i get “Segmentation Fault”?
Why does this code work? If the first element only hold the first characer, then where are the rest of characters being stored? And if this is possible, why aren't we using this method?
Notice line 11: static char c[1]. Using one element, you can store as much characters as you want. I use static to keep the memory location alive outside of the function when pointing to it later.
#include <stdio.h>
void PutString( const char* pChar ){
for( ; *pChar != 0; pChar++ )
{
putchar( *pChar );
}
}
char* GetString(){
static char c[1];
int i = 0;
do
{
c[i] = getchar();
}while( c[i++] != '\n' );
c[i] = '\0';
return c;
}
void main(){
PutString( "Enter some text: " );
char* pChar = GetString();
PutString( "You typed the following:\n" );
PutString( pChar );
}
C doesn't check for array boundaries, so no error is thrown. However, characters after the first one will be stored in memory not allocated by the program. If the string is short, this may work, but a long enough string will corrupt enough memory to crash the process.
You can write wherever you want:
char *bad = 0xABCDEF00;
bad[0] = 'A';
But you shouldn't. Who knows what the above lines of code will do? In the very best case, your program will crash. In the worst case, you've corrupted memory and won't find out until much later. (And good luck tracking down the source!)
To answer your specific questions, it doesn't "work". The rest of the characters are stored directly after the array.
You are just very (un)lucky, that you are not overwriting some other data structures. The array definitely cannot store as much characters as you want - sooner or later you either silently corrupt your memory (in the worse case), or hit a segfault by accesing a memory your process hasn't mapped. The fact that it works is likely because the compiler didn't place any other data after your c[1]. Just try to add a second array, let's say static char d[1]; after c, and then try reading from it - you'll see the second character from c.
C++ does not do bounds checking on arrays. That's for performance reasons; checking every array index to see if it's outside the bounds would incur an unacceptable runtime overhead. Avoiding overhead has always been a design goal of C++.
If you want bounds checking, you should use std::vector instead, which does provides it as an optional feature through std::vector::at().
In this case the behavior is undefined: according to the compiler / the current state of the memory / ..., it may seems to run fine, it may write corrupted chars, or it may crash because of a sefault.
Linking against Electric Fence or running in valgrind may help to find such errors at runtime.
I have written a code to read a file, store it in a structure and just display it. But somehow it is giving me a segmentation fault and I dont know why. Can someone please help me?
Output:
file: /home/neel/map2.txt
file opened
Start Intersection
a->road: 4
a->roadId[0]: 1
a->lane[0][0]: 2
a->lane[0][1]: 2
a->roadId[1]: 2
a->lane[1][0]: 2
a->lane[1][1]: 2
a->roadId[2]: 3
Segmentation fault
Code:
#include <iostream>
#include <fstream>
#include <stdio.h>
using namespace std;
struct Intersection
{
unsigned short road;
long long int *roadId;
short *lane[2];
};
int main(int argc, char** argv)
{
std::ifstream file;
cout<<"file: "<<argv[1]<<endl;
file.open(argv[1], std::ios::in);
cout<<"file opened"<<endl;
while (!file.eof())
{
cout<<"Start Intersection"<<endl;
Intersection *a = new Intersection;
file>>a->road;
a->roadId = new long long int[a->road];
a->lane[0] = new short[a->road];
a->lane[1] = new short[a->road];
cout<<"a->road: "<<a->road<<endl;
for (int i=0; i<a->road; i++)
{
file>>a->roadId[i];
cout<<endl<<"a->roadId["<<i<<"]: "<<a->roadId[i]<<endl;
file>>a->lane[i][0];
cout<<"a->lane["<<i<<"][0]: "<<a->lane[i][0]<<endl;
file>>a->lane[i][1];
cout<<"a->lane["<<i<<"][1]: "<<a->lane[i][1]<<endl;
}
cout<<"Intersection inserted"<<endl;
delete a;
}
}
Text file:
4
1
2
2
2
2
2
3
2
2
4
2
2
Your lane is an array of 2 elements, however when i reaches 2 in your inner loop you are trying to print a->lane[2][0], which doesn't exist.
file>>a->lane[i][0]; //wrong
file>>a->lane[i][1]; //wrong
The indices should be reverse:
file>>(a->lane[0][i]); //correct
file>>(a->lane[1][i]); //correct
I added brackets just for clarity.
Besides, there is memory leak in your program. There should be as many delete as there are new statements, to ensure that there is no memory leak. So write these:
delete [] a->roadId;
delete [] a->lane[0];
delete [] a->lane[1];
delete a; //you've written only this!
Note delete a should be the last statement when deallocating the memory!
I don't mean to be nasty, but this code has enough problems it's almost difficult to decide which ones to start with.
using namespace std;
Here's the first red flag. About all I can say is that using namespace std; is a poor idea. With other namespaces it can be acceptable, but with std, it should always be avoided (IMO).
struct Intersection
{
unsigned short road;
long long int *roadId;
short *lane[2];
};
This strikes me as a pretty poorly designed structure. std::vector is a good thing. Use it. Rather than just a structure of dumb data, you might want to consider defining operator>> for your structure type, so you can read one directly. Even if you don't do that, from the way you're using it, what you really want is something more like:
struct road {
long long Id;
short lane[2];
};
struct Intersection {
int road_count;
road *roads;
};
Then, rather than a couple of parallel arrays all the same size that have to be walked in parallel, you get a a number of roads, each with its own data. std::vector is still better though.
int main(int argc, char** argv)
{
std::ifstream file;
cout<<"file: "<<argv[1]<<endl;
file.open(argv[1], std::ios::in);
Rather than defining an ifstream object and then opening it separately, you should normally plan on passing the name to the ctor so it's defined and opened in a single operation, something like:
std::ifstream file(argv[1]);
But, you also normally want to add a bit of error checking so you only attempt to use the command line argument as a file name if one has been passed, something like this:
if (argc < 2) {
std::cerr << "Usage: your_command <filename>\n";
return EXIT_FAILURE;
}
Then you'd have the code to define the ifstream.
while (!file.eof())
Here's another major problem. A loop of this form is essentially always wrong (including this case, from the looks of things).
cout<<"Start Intersection"<<endl;
Intersection *a = new Intersection;
There seems to be no reason to allocate this dynamically. Are you, perhaps, a recovering (or perhaps not recovering) Java or C# programmer? Java requires that all objects of user defined classes be allocated dynamically, but C++ does not.
file>>a->road;
a->roadId = new long long int[a->road];
a->lane[0] = new short[a->road];
a->lane[1] = new short[a->road];
cout<<"a->road: "<<a->road<<endl;
for (int i=0; i<a->road; i++)
{
file>>a->roadId[i];
cout<<endl<<"a->roadId["<<i<<"]: "<<a->roadId[i]<<endl;
file>>a->lane[i][0];
cout<<"a->lane["<<i<<"][0]: "<<a->lane[i][0]<<endl;
file>>a->lane[i][1];
cout<<"a->lane["<<i<<"][1]: "<<a->lane[i][1]<<endl;
}
I'd prefer to separate the code for reading data from the code for displaying data. Except for things like homework (or debugging) you rarely want to display lots of raw data as you're reading it. In any case, the reading code should normally reside in the operator>> for that class, and the display code in operator<< for the class.
cout<<"Intersection inserted"<<endl;
This seems to be an outright falsehood. You haven't actually inserted an Intersection into anything.
delete a;
When you quit allocating the Intersection dynamically, you'll be able to eliminate this as well. If you insist on handling all the dynamic allocation by hand, you need to delete the components before this to avoid having memory leaks (another reason to prefer to std::vector).
I know that may sound pretty negative, and that leaves me a bit torn. On one hand, I'd really like to suggest better ways to do things. At the same time, this looks enough like homework that I'm extremely hesitant to just post better code either. I've tried to include a few hints about better ways, but realize they're probably not quite as specific as you'd like -- I apologize for that, but given that it's probably homework I don't think I can be a lot more specific.
Here is my code, I casted the buffer to different type of objects, is this what causes the failure? I really want to know why the FromBase::find2(int key) works, but not FromBase::find(int key)?
class Base
{
public:
virtual int find(int key)=0;
int keys[4];
};
class FromBase:public Base
{
public:
FromBase();
int find(int key);
int find2(int key);
};
FromBase::FromBase()
{
for(int i=0;i<4;i++)
keys[i]=-1;
}
int FromBase::find(int key)
{
for(int i=0;i<4;i++){
if(keys[i]==key)
return i;
}
return i;
};
int FromBase::find2(int key)
{
for(int i=0;i<4;i++){
if(keys[i]==key)
return i;
}
return i;
};
int main()
{
FromBase frombase;
FILE* fptr=fopen("object.dat","w");
fwrite((void*)&frombase,48,1,fptr);
fclose(fptr);
char object[48];
fptr=fopen("object.dat","r");
fread((void*)object,48,1,fptr);
// looks like this works
(FromBase*)object->find2(7);
//These two do not work, I got segmentation fault!
(FromBase*)object->find(7);
(Base*)object->find(7);
}
The reason I want to do this is because I need to read the object from a file, thus I need to cast the buffer to an particular type then I can call the mothod.
There is a high chance that you are overwriting the virtual function table with your code leading to a bad address when you call the method. You cannot just save objects into a file and expect to restore them by just restoring the memory content at the time they were saved.
There are some nice libraries like boost::serialization to save and restore objects. I would urge you to read about this or to turn your objects into plain old data types (structs) containing no references or addresses.
There are several reasons why this code is not guaranteed to work. I think the biggest concern is this code here:
char object[48];
The number 48 here is a magic number and there's absolutely no guarantee that the size of the object you're writing out is 48 bytes. If you want to have a buffer large enough to hold an object, use sizeof to see how many bytes you need:
char object[sizeof(FromBase)];
Moreover, this is not guaranteed to work due to alignment issues. Every object in C++ has an alignment, some number that its address must be a multiple of. When you declare a variable, C++ ensures that it has the proper alignment for its type, though there's no guarantee that it ends up having the alignment of any other type. This means that when you declare a char array, there's no guarantee that it's aligned the same way as a real FromBase object would be, and using the buffer as an object of that type results in undefined behavior.
As others have pointed out, though, you also have a problem because this line:
fopen("object.dat","r");
Doesn't update the local variable you're using to keep track of the file pointer, so what you're reading back is almost certainly going to be garbage (if you read back anything at all). The segfault is probably coming from the bytes for the virtual dispatch table not being read back in correctly.
// will these two methods work? I got segmentation fault!
(FromBase*)object->find(7);
(Base*)object->find(7);
No they will not work. The segmentation fault might be a hint ;)
object is a type on the stack, which is fine, but you need to call the class constructor. If this was valid c++, ANY memory could be casted to any class.
I'd start off by creating the class on the stack and call some Load()-method on it, e.g.
FromBase object;
object.Load("object.dat");
And let the Load()-method read the data from file and set values on the internal data.
Apart from all the other problems that people have pointed out.
I absolutely shocked that nobody has mentioned that:
(FromBase*)object->find2(7);
Is just NOT guaranteed to work.
You are depending on a raft of implementation details. object is an array of char! Not a FromBase thus the compiler has not had the chance to initialize any of its implementation dependent details.
Even if we assume that the implementation uses a vtable (and thus a vtable pointer in the class). Does the implementation use a relative pointer or an absolute pointer. Assuming you want to save with one run and then reload the next time? Are you assuming the vtable is actually located in the same location between different runs (what happens when you load this part of the application from a dynamic library)!
This is just horrible. You SHOULD NOT DO THIS EVER.
If you want to serialize and de-serialize the object from storage. Then the class has to know how to do the serialization itself. Thus all the correct constructors/destructors get called at the correct time.
First problem I can see when you use fopen second time:
fopen("object.dat","r"); //problem - your code
which should be this:
fptr = fopen("object.dat","r"); //fix (atleast one fix)
That means, in your code you're trying to read data using fptr which is already closed!
One problem is that the array of characters do not have a method called find.
The cast do not convert the array to FromBase or Base. It only tells the compiler to ignore the error.