Why does this code produce a segfault when running regularly, but undefined behavior instead of a segfault if I either add a command line argument or comment out calling the cpy function?
#include <cstdlib>
#include <iostream>
#include <cstring>
using namespace std;
int *p;
void fn() {
int n[1];
n[0]=99;
p = n;
}
void cpy(char *v) {
char x[8];
strncpy(x,v,8);
}
int main(int argc, char** argv) {
fn();
cpy(argv[1]);
cout << "p[0]:" << p[0];
}
I know n is a local var for the function fn, but is there a way I can overflow a buffer or enter something as argv[1] to get it to print the value that n held from wherever it is/was in memory?
If you don't pass an argument, then argv[1]==nullptr. Then cpy(argv[1]) is cpy(nullptr) and cpy invokes strncpy(x,nullptr,8) and segfaults.
If you comment out the cpy, then no segfault.
If you pass an argument, then cpy won't segfault. But then you get to a different problem: fn did p=n but n was declared on the stack, and so back in main at cout<<p[0], p points at the object n which no longer exists, and so the behavior is undefined.
Related
I have a big struct that needs to be processed. So I use std async to do it on another thread. Here is a simple example below:
#include <iostream>
#include <future>
using namespace std;
struct teststruct{
float thisvalue[32][32][64];
};
void foo(teststruct thisdummy) {
this_thread::sleep_for(chrono::milliseconds(234));
cout << "hello";
}
int main() {
teststruct thisteststruct;
foo(thisteststruct); // this does work
auto futurevalue = async(launch::async, foo, thisteststruct); //this doesnt work
return 0;
}
I have a struct that is just a big 3d array of floats. When I run this I get an error saying Bus error: 10. Just calling foo without using async works but using std async it doesn't work. Somehow it is related with the struct size since when I make the struct
struct teststruct{
float thisvalue[32][32][63];
};
it magically works. I have tried splitting up the struct by half so a 32x32x32 array instead of a 32x32x64 array and taking in teststructs as parameters but it doesn't work. As I said above I think this has to do with the size of the struct. How can I fix this?
You are probably blowing the stack.
sizeof(teststruct) is 32*32*64*sizeof(float). Assuming a 4-byte float, that's 256KB that you are attempting to pass by value into foo.
While there are flags you can pass to the compiler to increase stack size, you really want to avoid passing large objects by value. As that requires an in-memory copy to be made. Pass that big struct by shared_pointer. That will enable it to be passed around on the main thread and on the async thread without using any significant amount of stack memory. It's also faster since it avoids the large copy of that object.
#include <iostream>
#include <future>
#include <memory>
using namespace std;
struct teststruct{
float thisvalue[32][32][64];
};
void foo(shared_ptr<teststruct> thisdummy) {
this_thread::sleep_for(chrono::milliseconds(234));
cout << "hello";
}
int main() {
auto thisteststruct = make_shared<teststruct>();
foo(thisteststruct);
auto futurevalue = async(launch::async, foo, thisteststruct);
return 0;
}
Making it a pointer or reference should do the trick.
(untested)
void foo(teststruct *thisdummy) {
this_thread::sleep_for(chrono::milliseconds(234));
cout << "hello";
}
int main() {
teststruct thisteststruct;
foo(&thisteststruct); // this does work
auto futurevalue = async(launch::async, foo, &thisteststruct); //this doesnt work
futurevalue.get();
return 0;
}
What the below discussion is about is:
If the std::future obtained from std::async is not moved from or bound
to a reference, the destructor of the std::future will block at the
end of the full expression until the asynchronous operation completes,
essentially making code such as the following synchronous:
See this
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 6 years ago.
#include <iostream>
#include<string.h>
using namespace std;
char *rt()
{
char a[20];
strcpy(a,"I am a beginner");
cout<<a;
return a;
}
int main()
{
char *a;
a=rt();
cout<<endl;
cout<<a;
return 0;
}
Here I have made a short program for understanding the same....I was expecting the output to be as
I am a beginner
I am a beginner
UPDATE:
But it turned out to be
I am a beginner
ëóG
I have read many articles and post but I am not able to understand their complex language....so I will appreciate a no-nonsense answer ( for a stupid...like me!!)
UPDATE:
Actually, there is one question in my assignment which goes like this
class COMPUTER
{
char chiptype[10];
int speed;
public:
void showdetails()
{
cout<<chiptype;
cout<<"\t"<<speed;
}
void getdetails()
{
cin.getline(chiptype,10);
cin>>speed;
}
};
Here the data has to be read and stored into a binary file....and the records having chiptype as "CD" are to be displayed.
Now my question is that...as the variable chiptype is private so I can't use it for comparison in main()....so I thought of making a function which returned the value stored in chiptype.
And I am not allowed to use std::string as well as node implementation...
char a[20]; is allocated on stack. When the function rt() returns, the stack unwinds and a goes out of scope. Hence you do not get your desired result.
While you are on C++, may I suggest using std::string
Read the comment below:
The other trick is to wrap the array in a struct, and return the
struct. Since a struct is copyable, the array internally becomes
copyable and will not lose scope. See this answer. Then you're not
dealing with pointers at all. See this live example – PaulMcKenzie
Use std::string instead of char[]
#include <iostream>
#include<string>
std::string rt()
{
std::string a("I am a beginner");
std::cout<<a;
return a;
}
int main()
{
std::string a;
a=rt();
std::cout<<std::endl;
std::cout<<a;
return 0;
}
In your original code char a[20] is allocated on the stack and return a; will return a pointer to a stack variable that is no longer valid when you receive it in you main() -- handling strings in c++ should generally be done using std::string as it handles all the nasty memory management that wil kill your program if you aren't careful.
If you have to use pointers and not use std::string, you would need to go the c style way with the risk of having memory leaks if you miss a step or two. The code would look something like this using c style (keeping the cout c++)
#include <iostream>
#include <strings.h>
std::string rt()
{
char *a = malloc(20); // allocate the memory on heap
strcpy(a,"I am a beginner");
std::cout<<a;
return a;
}
int main()
{
char *a;
a=rt();
std::cout<<std::endl;
std::cout<<a;
free(a); // release the memory
return 0;
}
Caution: I don't recommend that you do the above style -- in a real world application you will likely get into trouble by either forgetting to free the memory, or accidentally accessing the memory after it has been free'd
The problem is that the memory of a will be destroyed as soon as program returns from the function. I do not think you should work with dynamic memory at your level of knowledge, so I suggest you define the array outside and just modify it inside the function:
#include <iostream>
#include<string.h>
#define MAX_LENGTH 20
using namespace std;
void rt(char *a)
{
strcpy(a,"I am a beginner");
cout<<a;
}
int main()
{
char a[MAX_LENGTH];
rt(a);
cout<<endl;
cout<<a;
return 0;
}
Furthermore, you should take care that rt is not writing more than MAX_LENGTH characters.
As mentioned by other use std::string instead of char [].
std::string rt()
{
std:: string a = "I am a beginner"; // This statement is equivalent to std::string a("I am a beginner");
std::cout << a "\n";
return a;
}
Main reason of not getting the desired result is " char a[] is allocated on stack, but when function return stack become empty.
P.S : You need to include <string> in your program, to use std::string
I have a string variable inside a vector that gets a string.
#include <vector>
#include <string>
using namespace std;
vector <string> buffer;
main(int argc, char *argv[]){
buffer[0] = "foobar";
return 0;
}
It causes this massive command line compiler error that starts with:
Multiple definition of WinMainCRTStartUP...
Then the error continues with roughly 500 lines of incoherent stuff.
I've successfully compiled other C++ programs with this compiler(GNU compiler). I don't know why this specific program is causing an error.
There are two problems. The first of all you need to add return type to main:
int main() {
...
}
Second. You have an empty buffer, so when your are doing buffer[0] = "anything" you will corrupt the memory (what may be discovered later when another function will access to the corrupted object). This happened because operator [] is unchecked for vector. If you will change it as:
int main() {
buffer.at(0) = "foobar";
return 0;
}
You will get an exception.
Both sections of code below are drastically simplified, isolated versions of my actual code. The examples are just big enough to reproduce the problem. The first section of code below works fine. The section section is an attempt to begin to make it part of a class. I'm trying to take tiny steps since small modifications to something like the struct shown below require lots of changes throughout the code which is full of pointers, pointer to pointers and references which all involve this struct. Can you tell me why the second section of code throws a stack overflow within it's constructor and what small changes can be made to fix it?
Working code:
#include <cstdio>
#include <cstdlib>
#include <iostream>
using std::cout;
using std::endl;
const int maxSize = 3;
struct Item{
int count;
Item *items[maxSize + 1];
};
void foo()
{
Item *p;
p = new Item();
p->count = 2;
cout << p->count << endl;
}
int main(int argc, char *argv[])
{
foo();
return 0;
}
Attempt to very gradually modify the code as a whole toward becoming a class:
#include <cstdio>
#include <cstdlib>
#include <iostream>
using std::cout;
using std::endl;
int maxSize = 3;
struct Item{
int count;
Item *items;
Item()
{
items = new Item[maxSize + 1]; // stack overflow
}
};
void Initialize(int size)
{
maxSize = size;
}
void foo()
{
Item *p;
p = new Item();
p->count = 2;
cout << p->count << endl;
}
int main(int argc, char *argv[])
{
Initialize(5);
foo();
return 0;
}
The first call to construct a Item calls new Item[maxSize+1], which calls the default constructor, which calls new Item[maxSize+1], which calls the default construct, and so on until you reach stack overflow.
All the answers are right. I want to suggest a solution for you:
Instead of initializing the array within the ctor, you could implement an initialization method like
init(int maxSize) {
items = new Item[maxSize + 1];
}
that you can call after having constructed the object. This should avoid the stack overflow. In general, you should avoid to place instances of an object inside the object itself. Its better to use Collections of the Item
List<Item>, std::vector<Item>, ...
It is because in working version you have reference to an array of object, but not actual object of Items. In second version, you are creating objects by using keyword new. So, in second version in constructor it will call itself! It will call it's own constructor infinite times. Hence, you see runtime exception stackoverflow :)
Above posters are right. Within the constructor of Item you create items (by creating an array). So the ctor is again called, which creates more items, which .... This is more or less an infinite loop which eats up your stack.
Either stick with the references or use a collection like List - so you can add the items later on dynamically.
for some reason, after creating an object in main func., the destructor gets called right away, isn't it supposed to get called only when main finishes? thanks
code:
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
class check{ //create class check
public:
string m_bank_name;
int m_check_number;
int m_branch_number;
char* m_check_sum;
check ( string bank_name, int check_number, int branch_number, char* check_sum){
int a_size = (strlen(check_sum)+1);
m_check_sum = new char[a_size]();
for (int i=0;i<a_size;i++)
{
m_check_sum[i]=check_sum[i];
}
m_bank_name= bank_name;
m_check_number = check_number;
m_branch_number = branch_number;
}
~check (){
delete [] m_check_sum;
cout<<"deleted!"<<endl;
}
};
void main(){
check ob1= check("poalim",809877,12,"4578");
cout<<ob1.m_check_sum<<endl;
getchar();
}
This expression
check("poalim",809877,12,"4578")
creates a temporary object that gets destroyed right after the full expression (;)
Before being destroyed, it is copied to ob1, which is destroyed at the end of the main function.
Perhaps you meant to write
int main(){ //note the correct return type of main
check ob1("poalim",809877,12,"4578"); //direct constructor call
cout<<ob1.m_check_sum<<endl;
getchar();
}
I really suggest that you should read a good book on C++ fundamentals.