One function tries to pass char array to another, but without success:
char * ret() {
char buf[32];
buf[0]='1'; // buf char array contains 1
buf[31]='\0';
printf(buf);
return buf;
}
int multiline() {
char temp[32];
strcpy(temp,ret()); // temp array doesn't contain 1 after this line
temp[31]='\0';
printf(temp);
}
Please tell me, how to fix this issue?
you are returning a pointer to a local variable char buf[32];. This array is allocated on the stack and only valid within the function but not outside of the function.
You get undefined behavior when you access this array.
To return an array like this you should allocate it on the heap, eg. with malloc()
You can fix the issue by not returning a local variable (allocate a string or return a pointer to a statically allocated one):
char * ret() {
char * buf = malloc(32*sizeof(char));
buf[0]='1'; // buf char array contains 1
buf[31]='\0';
printf(buf);
return buf;
}
int multiline() {
char temp[32];
char * returnedString = ret();
strcpy(temp,returnedString);
free(returnedString);
temp[31]='\0';
printf(temp);
}
You can't return a pointer to a local variable; as soon as the function returns, the local variable, along with the rest of the function's stack frame, is destroyed.
Instead, you can return a copy of the array; you could make one using strdup().
As an aside, you're setting the first character of your array, and putting a \0 at the end, but the 30 characters in between just hold garbage. Normally the \0 at the end of a string is immediately after the valid characters, not all the way at the end of the array.
Related
If I were to allocate a string like this would it be safe to work with? i.e. should I expect any UB when writing/reading to/from it?
void example()
{
char exmapleString[32];
char exmapleString[0] = '\0';
}
Even if exmapleString contains garbage data for not being initialized properly (i.e. char exmapleString[32] = { 0 };) I've set the first value of the exmapleString array to \0 therefore if I were to pass it through functions like strcpy, strcat, etc... The null terminator would be pushed to the end of the string so this means this string is safe to work with if I initialize it like this and set the first value of the array to \0?
So far from all of the testing I've done this seems to work just fine.
This function works
void example()
{
char exmapleString[32];
char exmapleString[0] = '\0';
strcat(exmapleString, "test");
print(exmapleString);
}
But this function will (most of the time) print garbage data
void example()
{
char exmapleString[32];
strcat(exmapleString, "test");
print(exmapleString);
}
Which leads me to beleive that yes indeed setting up a string like this
char exmapleString[32];
char exmapleString[0] = '\0';
Should not result in any UB. Is that correct? Or would this be considered un-safe?
I'm trying to make myself a program that will take a String and give me the word after a certain character. So, for example:
String theString = "hello \t world"; // or "borld \t bello";
After the tab, I only want "world" and not "hello." This keeps crashing on me for some reason.
size_t delimiter = theString.find_last_of('\t');
char *test;
if (theString.find("hello") != string::npos) {
strcpy(test, theString.substr(delimiter + 1).c_str());
else if (theString.find("borld") != string::npos) {
strcpy(test, theString.substr(delimiter + 1).c_str());
}
cout << test;
From strcpy manual:
char *strcpy(char *dest, const char *src);
The strcpy() function copies the string pointed to by src, including
the terminating null byte ('\0'), to the buffer pointed to by dest.
In your code, you declare test as a pointer to char* but you never initialize it.
test is therefore a pointer to indeterminate value. You then attempt to copy data to that inderminate location, resulting in the crash.
You can fix this easily by initializing test to point to memory you can strcpy to. Be sure to allow enough to not write beyond the buffer.
always the same mistake why you write to test without initializing it?
char *test; // no memory allocated so using it will cause a segfault
char test[50]; // just for explaining we allocate 50 bytes for pointer test
// char* test = new char[50]; // the same above but here dynamic memory
// delete[] test; // free up memory because dynamic memory is not automatically freed
I am playing around with socket programming on Qt. I am reading char array from server socket as client socket and returning the result as char pointer.
char* zgr_socket::sendMessage(){
char buffer[5];
while(1){
bzero(buffer,2);
n = read(sockfd,buffer,2);
if (n < 0){ }
close(sockfd);
return buffer;
}
}
And I am trying to get the resulting char array from in this method
void MainWindow::on_pushButton_2_clicked()
{
char* returnedChar = mySocket->sendMessage();
std::string aString(returnedChar);
QString myQString = QString::fromStdString(aString);
ui->label1->setText(myQString);
}
No matter what I've tried I couldn't manage to get the correct char array. When I debug an look at return buffer line it returns correct array, but after some kind of magic I get arbitrary values in aString variable. Can anybody see the reason, please?
You return a pointer to char buffer[5]; except that buffer is a local variable of the function, therefore after the function exits it ceases to exist. You now have a dangling pointer. Try returning a string from the function instead of a char* and just create the string as a part of the return statement.
There is a QString constructor which takes char pointer as parameter:
QString::QString(const char * str)
see more
how can i use the windows api without working with char and char * arrays. I want to work only with strings.
second question
char * nextdir(char * cstr) {
string mystring(cstr);
mystring.erase(mystring.find("*.*\\"),4);
mystring.append("\\*.*");
char nextdiir[MAX_PATH]="0";
strncpy( nextdiir, mystring.c_str(), sizeof( mystring ) );
cout<<"NEXTDIIR function="<<nextdiir<<endl;
return nextdiir; //}
the next dir is an array! how can i return it from function?
what happen if i cast it to char * array?
My problem is that other function that uses the nextdir returned value is working strange!
void recursive(char * searchdir){
cout<<"searchdir="<<searchdir<<endl;}
when im doing
recursive(nextdiir(foo)); //now the data printed is not the same but garbage! not like the data printed in call to nextdiir function!!
so i get for example
NEXTDIIR function=c:\windows\*.*
searchdir=garbage
//garbage is unknown characters!
how to fix it?
another questions!!
1)is it because i casted char array name to char * ?
2)how to use windows api without this char and char * mess . only work with strings?
3)what is the difference between char array and char *? the char array name is also constant pointer to the first element then what is the difference???
4)how to return char array from function in c ? in c++?
5)what is the differnce between char * and const char * ? they both the same cuz the value being pointed is unchangeable!
Please help
You are returning a pointer to local variable nextdiir. When the function returns, that variable ceases to exist, leaving you with a dangling pointer. De-referencing it is undefined behaviour.
Why not return an std::string? Then use the std::string::c_str() method to get a const char* pointer to its underlying data.
std::string nextdir(const char * cstr) {
string mystring(cstr);
// do your stuff
return mystring;
}
lots of questions...
how can i use the windows api without working with char and char * arrays. I want to work only with strings.
that will be hard, Win Api requires for some functions a pointer to char* array, you might use here std::vector<char> vec(REQUIRED_SIZE); pass &vec[0] to your api function, and assign &vec[0] to your std::string to get results into std::string.
Second question
char nextdiir[MAX_PATH]="0";
is local to your function, so you are not allowd to return its pointer (it will be UB). You can as above first create std::vector<char> and modify it as you want, and return result as a std::string(&vec[0]).
another questions!!
1)is it because i casted char array name to char * ?
not sure where is that cast, but you had a UB as stated above.
2)how to use windows api without this char and char * mess .
MFC CString allows you to access internal buffer using GetBuffer(0) or GetBufferSetLength(100). std::string does not allow you to safely modify internal buffer, thats why its best to use std::vector. Actually std::vector<TCHAR> would be better, in case you use UNICODE builds where TCHAR will be wchar_t.
3)what is the difference between char array and char *?
both points to array of char type, so no much difference.
the char array name is also constant pointer to the first element then what is the difference???
if it is const char* nm = "alabama"; then it says you cannot modify nm array content
4)how to return char array from function in c ? in c++?
to safely return a char array, you should make sure its lifetime is longer that your function lifetime. This means either you have to allocate memory inside function,- or pass already allocated memory to your function.
5)what is the differnce between char * and const char * ? they both the same cuz the value being pointed is unchangeable!
char* is an array of type char that you can modify in your code, const char* is an array of char type you can only read.
#include <iostream>
#include <string.h>
using namespace std;
void newBuffer(char* outBuffer, size_t sz) {
outBuffer = new char[sz];
}
int main(void) {
const char* abcd = "ABCD";
char* foo;
foo = NULL;
size_t len = strlen(abcd);
cout<<"Checkpoint 1"<<endl;
newBuffer(foo, len);
cout<<"Checkpoint 2"<<endl;
cout<<"Checkpoint 2-A"<<endl;
memset(foo, '-', len);
cout<<"Checkpoint 3"<<endl;
strncpy(foo, abcd, len);
cout<<"Checkpoint 4"<<endl;
cout << foo << endl;
int hold;
cin>>hold;
return 0;
}
This program crashes between checkpoint 2-1 and 3. What it tries to do is to set the char array foo to the char '-', but it fails because of some access issues. I do not understand why this happens. Thank you very much in advance!
Your newBuffer function should accept the first parameter by reference so that changes made to it inside the function are visible to the caller:
void newBuffer(char*& outBuffer, size_t sz) {
outBuffer = new char[sz];
}
As it is now, you assign the result of new char[sz] to the local variable outBuffer which is only a copy of the caller's foo variable, so when the function returns it's as if nothing ever happened (except you leaked memory).
Also you have a problem in that you are allocating the buffer to the size of the length of ABCD which is 4. That means you can hold up to 3 characters in that buffer because one is reserved for the NUL-terminator at the end. You need to add + 1 to the length somewhere (I would do it in the call to the function, not inside it, because newBuffer shouldn't be specialised for C-strings). strncpy only NUL-terminates the buffer if the source string is short enough, so in this case you are only lucky that there happens to be a 0 in memory after your buffer you allocated.
Also don't forget to delete[] foo in main after you're done with it (although it doesn't really matter for a program this size).
It fails because your newBuffer function doesn't actually work. The easiest way to fix it would be to change the declaration to void newBuffer (char *&outBuffer, size_t sz). As it's written, the address of the newly allocated memory doesn't actually get stored into main's foo because the pointer is passed by value.
You are passing the pointer by value. You would need to pass either a reference to the pointer, or the address of the pointer.
That said, using the return value would be better in my view:
char* newBuffer(size_t sz) {
return new char[sz];
}
When written this way, the newBuffer function doesn't really seem worthwhile. You don't need it. You can use new directly and that would be clearer.
Of course, if you are using C++ then this is all rather pointless. You should be using string, smart pointers etc. You should not have any need to call new directly. Once you fix the bug you are talking about in this question you will come across the problem that your string is not null-terminated and that the buffer is too short to hold the string since you forgot to allocate space for the null-terminator. One of the nice things about C++ is that you can escape the horrors of string handling in C.