I'm a newbie of C. Here I write a function to parse http post from browser. Here is my code:
char* HTTP_POST_GET_BODY(char* HttpPost){
char* HttpPostBody = strstr(HttpPost,"\r\n\r\n");
HttpPostBody = HttpPostBody + 4;
if(strcmp(HttpPostBody,"\r\n\r\n") != 0 && strcmp(HttpPostBody,"") != 0){
return HttpPostBody;
}
else{
char* HttpPostBody_IE;
HttpPostBody = strstr(HttpPost,"::");
char* HttpPostBodyEnd = strstr(HttpPost,"HTTP/1.1");
int body_length = HttpPostBodyEnd - HttpPostBody;
strncpy(HttpPostBody_IE,HttpPostBody+2,body_length-2);
return HttpPostBody_IE;
}
}
So basically, if the procedure goes in the "else" it should return a char pointer to caller. I check the debugger. HttpPostBody_IE has a value but when it return it is a null string.
char* http_body = HTTP_POST_GET_BODY(recieve_buffer);
Anyone has an idea about it?
You declare the pointer-variable HttpPostBody_IE but never allocate memory for it.
The call to strncpy(....) should create a core dump.
Try this:
int body_length = HttpPostBodyEnd - HttpPostBody;
HttpPostBody_IE = (char*)malloc(body_length+1);
strncpy(HttpPostBody_IE,HttpPostBody+2,body_length-2);
return HttpPostBody_IE;
Of course, make sure the caller of this functions releases the allocated memory afterwards.
You have a problem in case the function returns from within the if statement. This because no memory is allocated in that case.
You might resolve it this way:
static char HttpPostBody_IE[BIG_ENOUGH_FOR_ANY_SOURCE];
if (....)
{
...
}
else
{
...
strncpy(HttpPostBody_IE, ...);
return (HttpPostBody_IE);
}
Please notice that in this way the variable needs to be static.
Related
So i have a std::unordered_map, i want to acces to strings stored intro this map. I want to search intro intro all words inside the map and compare with a given word. If the strings are same then continue execution of the if statement.
{
public:
bool CheckFoo(const char* word);
protected:
typedef std::unordered_map<std::string, bool> word_map;
word_map words_map;
};
bool CheckFoo(const char* word)
{
if (words_map.empty())
{
return false;
}
auto it = words_map.begin();
while (it != words_map.end())
{
const std::string &r = it->first;
const char* tmp = word;
if (strcmp(tmp, r.c_str() ) == 0)
{
return true;
}
}
return false;
}
if ( CheckFoo("wordFoo") )
{
// bla bla
}
The problem is that those codes generate a .core dump file..
Do you see any mistakes in my codes?
The crash core analyze point me to strcmp line
Can't write comments yet but,
Like Nunchy wrote, tmp is not defined in that context.
I also noticed that your code never increments the map iterator, which would result in a never ending loop.
I'm assuming you did not copy your actual code into your post but instead rewrote it hastily which resulted in some typos, but if not, try making sure you're using temp and not tmp in your call to strcmp, and make sure the loop actually increments the iterator.
Like one of the comments on your post points out as well, make sure you actually have data in the map, and the function parameter.
You are declaring temp then referencing tmp which doesn't exist:
const char* temp = word;
if (strcmp(tmp, r.c_str() ) == 0)
Does this compile? Surely it should be:
const char* temp = word;
if (strcmp(temp, r.c_str() ) == 0)
?
This is a function to open a file dialog in Windows and return a string with the file name:
#include <windows.h>
#include <commdlg.h>
#include <string.h>
char* openFileDlg(char FileTypes[]);
char* openFileDlg(char FileTypes[]){
OPENFILENAME ofn;
char szFile[260];
HWND hwnd;
HANDLE hf;
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
strcpy(ofn.lpstrFilter,FileTypes);
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if(GetOpenFileNameA(&ofn)){
char *toReturn;
sprintf(toReturn,"%s",ofn.lpstrFile);
return toReturn;
}
else{
return NULL;
}
}
When I call this function and open a file, the process ends and returns value 3 (which means there is an error). How can I do so that this function returns a string with the path of the selected file?
Edit: I've changed my code to this and it still doesn't work:
#include <windows.h>
#include <commdlg.h>
#include <string.h>
void openFileDlg(char *toReturn[],char FileTypes[]);
void openFileDlg(char *toReturn[],char FileTypes[]){
OPENFILENAME ofn;
/*
Code for the settings of the GetOpenFileNameA, irrelevant in this question.
If you really need to know what's here, look at the code above.
*/
if(GetOpenFileNameA(&ofn)){
strcpy(*toReturn,ofn.lpstrFile);
}
else{
sprintf(*toReturn,"");
}
}
I should also say that if I press the Cancel button in the open file dialog box instead of selecting a file, it works fine. After some tests, I've noticed that it's the line strcpy(*toReturn,ofn.lpstrFile); that causes the error.
The pointer variable toReturn doesn't point anywhere, using it in any way without initializing it (i.e. making it point somewhere valid and big enough) will lead to undefined behavior
You have two solutions really:
Allocate memory dynamically and return a pointer to that. This of course requires the caller to free the memory when done with it.
Have the function take another two arguments: A pointer to a buffer and the length of the buffer. Then copy the string into that buffer, and return a boolean "true" or "false" success/failure status.
I recommend solution number two.
On an unrelated note, there's no need to use the expensive sprintf function in your case, a simple strcpy (or strncpy if you go with the second solution) will do.
You also have to remember in both cases that strings in C have an actual length of one more than e.g. strlen reports, for the terminating '\0' character.
In general, if you want to return a string in C, I'd use one of the following methods:
1) pass in a string buffer for the method to write to:
int openFileDlg(char FileTypes[], char* toReturn, int bufLen) {
/* ... */
snprintf(toReturn, bufLen, /* what you want to print */);
return ERROR; // status-code
}
/* ... */
char errorBuf[80];
int result;
result = openFileDlg(..., errorBuf, sizeof(errorBuf));
2) allocate memory, expect caller to free it:
char* openFileDlg(char FileTypes[]) {
/* ... */
char *toReturn = malloc(/* big enough */);
sprintf(toReturn, /* what you want to print */);
return toReturn;
}
/* ... */
char* error = openFileDlg(...);
if (error) {
/* ... */
free(error);
}
personally, I'd prefer (1) because it's safer. Option (2) is nicer to the API of the function, but has a risk of memory leaks if you forget to free the returned buffer. In a bigger project (especially with multiple people working on it) this is a very real risk.
(I realise this is pretty much the same as Joachim's answer, but his went up as I was writing mine)
You did not allocate memory for your return value. If you know the length of ofn.lpstrFile you could do this:
char *toReturn = malloc( (sizeOfLpstrFile + 1) * sizeof(char)) ;
sprintf(toReturn,"%s",ofn.lpstrFile);
return toReturn;
Still I consider this a bad idea because the calling function will have to free the memory which is not obvious from the interface.
Considering the following functions:
int get_timestamp(json_object *json_obj, double *timestamp) {
json_object *value_obj;
int status;
if (json_object_object_get_ex(json_obj, "timestamp", &value_obj)) {
if (json_object_is_type(value_obj, json_type_double)) {
*timestamp = json_object_get_double(value_obj);
status = JSONPARSER_OK;
}
else
status = JSONPARSER_EBADTYPE;
} else
status = JSONPARSER_ENODENOTFOUND;
free(value_obj);
return status;
}
int get_display_name(json_object *json_obj, char **display_name) {
json_object *value_obj;
int status;
const char* holder;
if (json_object_object_get_ex(json_obj, "display_name", &value_obj)) {
if (json_object_is_type(value_obj, json_type_string)) {
// The returned string memory is managed by the json_object and will
// be freed when the reference count of the json_object drops to zero.
holder = json_object_get_string(value_obj);
strcpy(*display_name, holder);
status = JSONPARSER_OK;
}
else
status = JSONPARSER_EBADTYPE;
} else
status = JSONPARSER_ENODENOTFOUND;
free(value_obj);
return status;
}
int get_organization(json_object *json_obj, char **organization) {
json_object *value_obj;
int status;
const char* holder;
if (json_object_object_get_ex(json_obj, "organization", &value_obj)) {
if (json_object_is_type(value_obj, json_type_string)) {
// The returned string memory is managed by the json_object and will
// be freed when the reference count of the json_object drops to zero.
holder = json_object_get_string(value_obj);
strcpy(*organization, holder);
status = JSONPARSER_OK;
}
else
status = JSONPARSER_EBADTYPE;
} else
status = JSONPARSER_ENODENOTFOUND;
free(value_obj);
return status;
}
Used as:
json_object *response_obj, *idp_obj;
int status;
char *display_name;
char *organization;
response_obj = json_tokener_parse(raw_data);
json_object_object_get_ex(response_obj, "idp", &idp_obj);
get_timestamp(response_obj, timestamp);
get_display_name(idp_obj, &display_name);
get_organization(idp_obj, &organization);
free(idp_obj);
free(response_obj);
return status;
What happens:
1) by removing get_organization(idp_obj, &organization); everything seems work fine;
2) by removing get_display_name(idp_obj, &display_name); everything seems work fine again;
3) with the code "as is", there is an error on the strcpy used inside the method get_organization:
No source available for "__strcpy_sse2_unaligned() at 0x7ffff763f001"
I would really like to understand this behavior in order to improve my knowledge in this amazing but hard languages.
That error message is a debugger error message, because it's in a function which it can't locate source to. The only thing you need to do is to walk up the function call stack until you reach your code.
As for why the debugger stops in that function, that's really should be another question, but I'll answer it anyway: It's because of undefined behavior because the destination pointer you pass to it is an uninitialized local variable: display_name. In the code where you call get_display_name you declare the local variable display_name, but you don't initialize it. The value of uninitialized non-static local variable is indeterminate, and using them without initialization leads to undefined behavior.
You have basically two solutions to this problem: Either declare display_name as an array of a fixed size, or use make it point to valid allocated memory, for example by using malloc.
You will also have the same problem with the organization variable.
for one of my project i have to make a new version of the function insertString,you could see the code below:
This function always gives me the desired result, (I made some Unit test), however the main issue is this one: even if it works in my IDE (compilation etc) it won't pass unit test using Valgrind, is there anyone who could see the error?
char * insertString(const char * src, int insertPosition, const char * toBeInserted,int insertLength)
{
size_t outputSize=stringLength(src)+(size_t)insertLength;
char* output=malloc(sizeof(char)*(outputSize+1));
int i;
if(output==NULL)
{
fatalError("error during memory allocation in InsertString");
}
for(i=0;i<insertPosition;i++)
{
output[i]=src[i];
}
for(i=0;i<insertLength;i++)
{
output[i+insertPosition]=toBeInserted[i];
}
for(i=0;i<=insertLength;i++)
{
output[i+insertPosition+insertLength]=src[insertPosition+i];
}
output[outputSize]='\0';
return output;
}
thank's for everything, and have a good Sunday!
The terminating condition, i<=insertLength, in your last loop:
for(i=0;i<=insertLength;i++)
{
output[i+insertPosition+insertLength]=src[insertPosition+i];
}
has nothing to do with the length remaining in src. If insertLength is large enough, the code will read past the end of src.
Change it to something like (I think):
for(i=0;i<=strlen(src)-insertPosition;i++)
{
output[i+insertPosition+insertLength]=src[insertPosition+i];
}
Also, in my opinion the code could be made much more easily understood (and therefore verifiable) by using a running index for the output buffer instead of resetting it to 0 for each loop and adding other values for the subscript. Alternatively, I think using pointers to traverse the various buffers would be more readable:
char* tmp = output;
for(i=0;i<insertPosition;i++)
{
*tmp++ = *src++;
}
for(i=0;i<insertLength;i++)
{
*tmp++ = *toBeInserted++;
}
for(i=insertPosition;i<=strlen(src);i++)
{
*tmp++ = *src++;
}
*tmp++ = '\0';
I have some code in the following kind of layout, I believe that the topExample/botExample aren't being set properly when I call addTopBotExample. I think this is due to the top bot variables being on the functions stack and so being cleared when the function ends? I have a feeling that perhaps I need to malloc the memory first, but am not sure how I would go about doing this are even if its the right approach.
typedef struct Example Example;
struct Example {
/* normal variables ...*/
Example *topExample;
Example *botExample;
};
....
void addTopBotExample(Example **example, int someVariable) {
Example top = createTopExample(int someVariable); //(createTopExample returns a
//type Example based on some input)
Example bot = createBotExample(int someVariable);
(*example)->topExample = ⊤
(*example)->botExample = ⊥
return;
}
If createTopExample isn't allocating memory, this is going to cause problems the moment it's called more than once. Rewrite createTopExample and createBotExample to use malloc and return an Example*. Something like this:
Example* createTopExample(stuff)
{
Example *example = malloc(sizeof(Example));
// ... stuff you do
return example;
}
Then your addTopBotExample would look like this:
void addTopBotExample(Example **example, int someVariable) {
if ((*example)->topExample)
free((*example)->topExample)
if ((*example)->botExample)
free((*example)->botExample)
(*example)->topExample = createTopExample(int someVariable);
(*example)->botExample = createBotExample(int someVariable);
return;
}
Note that this addTopBotExample will free the allocated memory before calling malloc again but before your program ends, you need to call free on any lingering Examples that used this addTopBotExample function:
free(exampleInstanceThatWasPassedIntoAddTopBotExampleAtSomePoint.topExample);
free(exampleInstanceThatWasPassedIntoAddTopBotExampleAtSomePoint.botExample);
You have already everything together. Allocate the Example in createTopExample or createTopExample
Example *createTopExample(int someVariable)
{
Example *x = malloc(sizeof(Example));
/* initialize x */
return x;
}
and in addTopBotExample
void addTopBotExample(Example *example, int someVariable) {
Example *top = createTopExample(int someVariable); //(createTopExample returns a
//type Example based on some input)
Example *bot = createBotExample(int someVariable);
example->topExample = top;
example->botExample = bot;
return;
}
Ooooo, this is bad. The expression "Example top" in the addTopBotExample() function allocated that object on the stack. It'll be trashed after exiting from the function. (Same for "Example bot" on the following line.) Something like this will work better:
void addTopBotExample(Example **example, int someVariable) {
Example *top = createTopExample(someVariable); // NOTE THE *
Example *bot = createBotExample(someVariable); // NOTE THE *
(*example)->topExample = top; // NOT &top !!
(*example)->botExample = bot; // NOT &bot !!
return;
}
And you'll want to write createTopExample and createBotExample so they return pointers:
#include <stdlib.h> // For malloc!
Example *createTopExample(stuff) // Note *. It's returning a pointer.
{
Example *example = malloc(sizeof(Example)); // Allocate on the HEAP. Lives after this function call.
// Fill in the fields of example.
example->field1 = 25; // Note the "->": you're dereferencing a pointer.
example->title = "Example title";
return example;
}