I'm having a data abort exception in my code. It is very likely I am doing a very bad operation with chars. This code seems to work, but I wonder if it is actually invalid. The question is, what happens if you copy the data of one struct to another with char arrays involved. How is the data copied?
I have two functions, one which will purposefully leak, because I want to also know what happens if the struct created with new lives on purposefully, but the struct whose data it copied goes out of scope.
// Example program
#include <iostream>
#include <string>
#include "string.h"
typedef struct {
char name[12];
char stupid[12];
int hello;
} tFile;
void CopyFileAndDelete(tFile *file1){
tFile *file2 = new tFile;
*file2 = *file1;
std::cout << file2->name << std::endl;
delete file2;
}
void CopyFileAndLeak(tFile *file1){
tFile *file2 = new tFile;
*file2 = *file1;
std::cout << file2->name << std::endl;
}
int main()
{
tFile file1;
memset(&file1, 0, sizeof file1);
file1.hello = 22;
snprintf(file1.name, 12, "%s", "hellogoodfriendhwoareyou");
snprintf(file1.stupid, 12, "%s", "greate");
CopyFileAndDelete(&file1);
CopyFileAndLeak(&file1);
}
Other than this code being generally unsafe and more C than C++, it's correct (other than the leak.) There is no way this can produce an exception (unless new throws due to memory allocation failure.)
Arrays inside structs will be copied as you'd expect. The compiler will generally do a memcpy() to copy them (or a special memcpy-like built-in to optimize the copy operation.)
This isn't code you should write though. Use std::string instead. Don't use new and delete, use value types instead. If you really need to allocate, use unique_ptr or shared_ptr to do it.
Don't write code like this in C++ :-)
Related
Based on the idea of this entry Is it a good idea to return “ const char * ” from a function?
I thought to extend this with another question I have.
Consider the following code:
#include <string>
#include <cstdio>
const char * GetSomeString()
{
std::string somestlstring;
somestlstring = "Hello World!";
return somestlstring.c_str();
}
int main()
{
const char * tmp = GetSomeString();
printf("%s\n", tmp);
return 0;
}
If I build it with
g++ source.cpp -o executable
and execute that, I get strange symbols displayed. This is because somestlstring is destroyed through the callstack and the pointer you keep after returning became invalid.
My question is: how should I design a method or function that does not have such behaviour without actually declaring additional global variables or potential member functions?
You should drop the whole C mindset and start writing C++:
#include <string>
#include <iostream>
std::string GetSomeString()
{
std::string somestlstring;
somestlstring = "Hello World!";
return somestlstring;
}
int main()
{
std::string tmp = GetSomeString();
std::cout << tmp << std::endl;
return 0;
}
One obvious solution is to make the return type std::string.
how should I design a method or function that does not have such beahviour without actually declaring additional global variables or potential member functions?
Not at all. If you return a const char *, your function is kind of telling the caller "here you have a C string to use, but it stays mine" *), and this implies the caller doesn't have to bother releasing the resources, for example. So you can do this from an instance method (returning a pointer to a field) or you can have a function return a pointer to some static buffer (global variable).
If you want to return a dynamically allocated C string from a function, you must return char * instead and the caller has to free() it when done using it.
That all said, in C++ this doesn't make much sense, except when somehow interfacing with C code. If you want to write C++ code, go with nvoigt's answer.
*) this is thinking in terms of ownership, which is very helpful dealing with manually managed resources. The owner of something is responsible for appropriate cleanup. You can only return a const raw pointer if you don't transfer ownership of the object to the caller.
You are currently referencing the memory of a local std::string object which is destroyed when the object goes out of scope (when returning from the function)
if you really want to return a const char *:
you have to make your std::string static (but only 1 value is shared by your application)
or you have to duplicate the string memory (but you need to free it or you get memory leaks, like happened a lot with the old str() method of the old strstream object, which was later converted to std::string)
But as others said, better stick to C++ std::string (or const reference) as a return value and take c_str() of that returned string when needed for C-style interfaces.
std::string tmp = GetSomeString();
FILE *f = fopen(tmp.c_str(),"r");
The local string variable in the GetSomeString() function will get out of scope after you returned from the funtion. You will be printing random stuff that is in the memory position where the string was before. Try this:
#include <string>
#include <cstdio>
void GetSomeString(std::string& str)
{
str = "Hello World!";
}
int main()
{
std::string str;
GetSomeString(str);
std::cout << str << std::endl;
return 0;
}
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 am having trouble understanding proper usage of the new keyword. My question is:
Is the following just bad design as I suspect?
If not, where should I call delete?
If so, what is the better practice?
#include <string>
#include <iostream>
struct myOptions {
int myInt;
std::string myString;
};
myOptions* packageOptions() {
myOptions* options = new myOptions;
options->myInt = 42;
options->myString = "hello world";
return options;
}
int main() {
myOptions* options = packageOptions();
std::cout << options->myString << std::endl;
std::cout << options->myInt << std::endl;
delete myOptions; // this just feels wrong to put here
}
My gut is telling me it's bad because the main function shouldn't have to manage the memory allocated by other functions, as in it's breaking some kind of encapsulation. I thought about doing a class constructor/deconstructor, but that seems to be overkill.
There is no reason to have to chase around memory manually as you are doing. I would just declare your variable on the stack, and return it by value. Then let RAII clean up the memory for you when the variable falls out of scope.
myOptions packageOptions() {
myOptions options;
options.myInt = 42;
options.myString = "hello world";
return options;
}
int main() {
myOptions options = packageOptions();
std::cout << options.myString << std::endl;
std::cout << options.myInt << std::endl;
}
The delete keyword should only appear inside the implementation of smart pointer classes. You can either return by value as Cyber suggested, or in cases where that isn't ideal (for example, return by value causes slicing of derived types) you can return std::unique_ptr and store it in a local variable of the same type, and the destructor will automatically clean up the object and its memory when the pointer goes out of scope.
"Doing a class constructor/destructor" for each case would be overkill. Just take advantage of the existing highly reusable smart pointers.
From a strictly technical perspective, what you are doing is fine.
But you asked what the proper use of new is [in C++] -- and the answer may surprise you.
The most proper way to use new is not to. The same can be said of delete. Instead of using new/delete, you should be using smart pointers such as std::shared_ptr along with an accompanying make_shared.
I'm not saying there are no exceptions, but those exceptions would be unusual and typically the result of a design that could be otherwise modified.
In fact, I would also suggest another question altogether: what is the proper use of dynamic allocation? Again, the answer I would suggest is don't use dynamic allocation. Obviously there are exceptions to this as well, in fact more exceptions than the "don't use new" guideline above -- but as you become more experienced both with the syntax and the semantics of the C++ language, you will find that dynamic allocation is needed in fewer scenarios.
Using shared_ptr is not the best option in your present case. I give this example to show you it exists, and then you don't have to bother about who/when the object is deleted. The shared_ptr will call the destructor/delete whenever there are no references on the object left, ie at the end of main in your example. (also shared_ptr has been introduced in C++11, not available in C++03)
#include <string>
#include <iostream>
#include <memory>
struct myOptions {
int myInt;
std::string myString;
};
using OptionsPtr = std::shared_ptr<myOptions>;
OptionsPtr packageOptions() {
OptionsPtr options = std::make_shared<myOptions>();
options->myInt = 42;
options->myString = "hello world";
return options;
}
int main() {
OptionsPtr options = packageOptions();
std::cout << options->myString << std::endl;
std::cout << options->myInt << std::endl;
}
Anyway, in your case, stack allocation, like in #Cyber answer, is much preferable.
Instead of using structures in this manner, try to use classes and constructors/destructors for the same.
What you have demonstrated is correct as far as managing the memory goes. But stylistically and from a maintenance point of view, it could be much better.
Two ways that are easier to maintain are:
using smart pointers
Redesigning your code so that you pass in a structure to optionsPackage, allowing the function to populate the passed in structure, and the called to worry about the lifespan and usage of the structure.
Smart pointers were created to help prevent memory leaks, which can be a long term pain to find in large projects. Look into std::shared_ptr or see the shared pointers suggested answers.
Passing in the actual structure allows the caller to worry about the memory space used, including allocating and deallocating it. This was the preferred way, before smart pointers came along, and is still the rule of thumb (letting the code that needs the data manage the data object associated with it).
Passing in the actual structure would make the code look something like this:
#include <string>
#include <iostream>
struct myOptions {
int myInt;
std::string myString;
};
void packageOptions( myOptions& theInputOptions) {
theInputOptions.myInt = 42;
theInputOptions.myString = "hello world";
}
int main() {
myOptions options;
packageOptions( options );
std::cout << options.myString << std::endl;
std::cout << options.myInt << std::endl;
}
I find this style far easier to maintain the code. It can be combined with smart pointers where needed.
I'm trying to learn about pointers and first class objects in C++. I'm sure the problem exists in my pointer assignments or calls. I was wondering if someone could help me to better understand pointers as well as using static variables/methods.
FirstClass.h
#pragma once
class FirstClassObject {
public: FirstClassObject();
FirstClassObject(int);
FirstClassObject(int, FirstClassObject);
static void next_attr();
static int attribute;
int num;
FirstClassObject *buffer;
FirstClassObject *next;
~FirstClassObject();
};
FirstClassObject.cpp
#include "FirstClass.h"
#include <stdlib.h>
#include <string>
using namespace std;
FirstClassObject::FirstClassObject(){
num = attribute;
next_attr();
};
FirstClassObject::FirstClassObject(int attr){
num = attr;
next_attr();
}
FirstClassObject::FirstClassObject(int attr, FirstClassObject object){
num = attr;
next_attr();
buffer = (FirstClassObject*) malloc(5);
memcpy(buffer,&object,1);
next = buffer;
}
void FirstClassObject::next_attr(){
attribute++;
}
FirstClassObject::~FirstClassObject(){
free(buffer);
free(next);
}
FirstClassObject_test.cpp
#include "FirstClass.h"
#include <iostream>
using namespace std;
int FirstClassObject::attribute = 0;
FirstClassObject get_next_object(FirstClassObject object){
FirstClassObject next_object;
next_object.buffer = object.next;
return next_object;
}
int main(){
FirstClassObject object;
FirstClassObject otherobject(4, object);
cout << get_next_object(otherobject).num << "these numbers should be the same " << object.num << '\n';
return 0;
}
Thanks in advance.
First and foremost, this is wrong:
buffer = (FirstClassObject*) malloc(5);
memcpy(buffer,&object,1);
malloc() is not the same as new[].
Your FirstClassObject type is a non-POD type since it has a non-trivial destructor. This means you cannot properly construct it using malloc(). All malloc() does is allocate memory, and that's it. You need to actually construct a FirstClassObject object, and to do that using dynamically, you use new[ ].
Secondly, malloc() requires the number of bytes to allocate. What is sizeof(FirstClassObject)? I bet it isn't 5 (the argument you gave to malloc()). But the main point is that even if you gave malloc() the correct number of bytes, you aren't properly constructing your objects by using it.
Third, because FirstClassObject is non-POD, usage of memcpy() is also not good. In short, memcpy() does not copy objects. To copy an object, you invoke the copy constructor.
It looks like you're reading C language books and/or reading C language resources, not C++ books and resources. If you are, put down the C for a bit and learn C++ from the proper sources. If you attempt to mix C with C++ (without the proper experience), you wind up with issues such as your example.
First:
buffer = (FirstClassObject*) malloc(5)
This allocates a buffer of size 5, not 5 FirstClassObject. To do this, you need to do something like:
buffer = (FirstClassObject*) malloc(5*sizeof(FirstClassObject));
Second:
memcpy(buffer,&object,1);
This copies only 1 byte out of your object struct. Not a complete object. Here, sizeof is your friend as well although it is dangerous as receiving buffer is not a fully constructed object.
Then this line:
next_object.buffer = object.next;
would do member to member copy(providing it compiled as you are trying to affect an object to a pointer) effectively writing pass the boundary of your previously under-allocated buffer giving you the assert.
So I've this issue I can't get fixed :-(
In my .h I've this:
protected:
char* _textPath_1;
FileReader* _reader_3;
in .cpp I've:
_reader_3 = new FileReader();
_textPath_1 = "foo";
_reader_3->openFile(_textPath_1);
And FileReader has this:
private:
char* fileName;
public:
signed int openFile(char* name);
but If I write this (just to test):
signed int FileReader::openFile(char* name) {
std::cout << name << std::endl;
fileName = name;
stream.open(fileName, std::ios::in);
if (!stream.is_open()) {
FileReader::printErrorOpeningFile(fileName);
stream.close();
return -1;
}
return 0;
}
fileName is a char * and I need that it gets the same value (foo) of name. I get an error, and I'm not even able to print name, it just print a blank line.. why?
EDIT: it's not working even using strcpy.. Actually inside the function I can't print the value of name, it's like it has been "deininitialized"
You need to allocate space for your text string _textPath_1.
Try this instead.
char myTextString[] = "foo";
_textPath_1 = myTextString;
This creates a local character array (a character string), which is initialized to "foo\0". It then copies that character string's address to your char pointer _textPath_1. As a LOCAL storage, it will only be valid in the local code block and will not be usable once your code has dropped out of its scope. If you need that string past the local code block, you will need to allocate it from heap memory (using new for instance) and remember to deallocate it after you are done with it.
You cannot use strcpy with your unallocated pointer because strcpy expects the destination char* to be pointing at a character array acting as your destination string buffer. As you haven't allocated any char space at all, it cannot copy "foo" into your _textPath_1, and that's why you get a runtime error when you try to strcpy it.
These and other fun with char* is why std::string was invented. No worries about allocating and deallocating space, having to use strcpy to copy its value, etc etc etc. Consider using std::string _textPath_1 in place of your char* _textPath_1.
You have to allocate _reader_3 before calling the function.
FileReader* _reader_3 = new FileReader;
I assume fileName is your member variable. Accessing pointers without initialization will result in unpredictable results
If you're really defining global variables in your header file:
char* _textPath_1;
FileReader* _reader_3;
Then you shouldn't be doing that. Global variables should be declared in header files, but defined in an implementation file.
This code works fine:
#include <iostream>
#include <fstream>
struct FileReader {
char* fileName;
std::fstream stream;
signed int FileReader::openFile(char* name) {
std::cout << name << std::endl;
fileName = name;
stream.open(fileName, std::ios::in);
if (!stream.is_open()) {
FileReader::printErrorOpeningFile(fileName);
stream.close();
return -1;
}
return 0;
}
void printErrorOpeningFile(char *) {}
};
int main() {
char* _textPath_1;
FileReader* _reader_3;
_reader_3 = new FileReader();
_textPath_1 = "foo";
_reader_3->openFile(_textPath_1);
delete _reader_3;
}