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.
Related
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.
I am working on building a threads library and for some reason have run into a simple malloc problem that I can't fix right now. I'm sure it's something simple I'm just missing it.
In my main.c I have the following code:
//declare testSem
tasem_t testSem;
int main(int argc, char **argv){
ta_libinit();
//initialize testSem
ta_sem_init(&testSem, 5);
//wait test
ta_sem_wait(&testSem);
the relevant code in my thread library is as follows:
void ta_sem_init(tasem_t *sema, int value)
{
//malloc the semaphore struct
sema = malloc(sizeof(tasem_t));
//error check
if(sema == NULL)
{
printf("could not malloc semaphore");
exit(0);
}
//initialize with the given value
sema->val = value;
printf("SemaVal = %i\n", sema->val);
}
void ta_sem_wait(tasem_t *sema)
{
printf("SemaVal = %i\n", sema->val);
if(sema->val <= 0)
{
//not done yet
printf("SWAPPING\n");
}
else
{
printf("SemaVal = %i\n", sema->val);
sema->val = sema->val + 1;
}
}
Here is the struct from my header file:
//struct to store each semas info
typedef struct tasem_t_struct
{
//value
int val;
//Q* Queue
//int numThreads
}tasem_t;
The output I get from this is:
SemaVal = 5
SemaVal = 0
SWAPPING
So evidently, I'm not mallocing my struct correctly as the value inside is lost once I go out of scope. I know I must just be forgetting something simple. Any ideas?
You can't seem to decide who's responsible for allocating your tasem_t structure. You have a global variable for it and pass its address to ta_sem_init. But then you have ta_sem_init dynamically allocate a brand new tasem_t structure, saving its address to sema, a local function argument, so that address gets lost when it falls out of scope.
Pick one, either:
Make ta_sem_init initialize an existing tasem_t variable.
Make ta_sem_init allocate and initialize a new tasem_t structure and then return its address (either directly or via a tasem_t** output parameter).
So far I have gotten my libev code to successfully return a static sting that says "OMP OMP", however when I write a function that returns a "static" string it never seems to work. (Sidenote: the idea is to turn that same function into a dynamic response but just for agile testing purposes I need this to work first). My code for the libev read callback is as the following...
void p2pserver_network_buf_read_callback(struct bufferevent *incoming, void *arg){
//Define function local variables
struct evbuffer *evreturn;
char *req;
//Begin function local logic
req = evbuffer_readline(incoming->input);
if (req == NULL){
return;
}
char *response;
parse_json_command(req, response);
//response = "OMP OMP";
g_print("PARSED");
evreturn = evbuffer_new();
evbuffer_add_printf(evreturn, "%s", response);
bufferevent_write_buffer(incoming,evreturn);
evbuffer_free(evreturn);
free(req);
g_print("%s", response);
}
The parse_json_command function is as the following...
void parse_json_command(char json_command, char *response){
//Define Local Variables
g_print("PARSING");
response = "YOU KNOW";
//Print out the recieved message....
//g_message("%s", json_command);
/**
* TODO: check if the JSON is valid before parsing
* to prevent "Segmentation Defaults"
* and its good sanity checks.
**/
//Parse JSON incomming
/*json_object * jobj = json_tokener_parse(json_command);
enum json_type type;
json_object_object_foreach(jobj, key, val){
g_print("%s\n", key);
if(g_utf8_collate(key, "cmd") >= 0){
//Looks like the user has sent a "cmd" (command), lets analyze the "val" (value) of that command to see what the caller/client needs to be attending to...
//Is the client requesting an "Identity Update" (Pings server: if this is the first time ping, the server and client will exachange keys if the relationship exists the server just accepts the encrypted "ping" packet update)
type = json_object_get_type(val);
if(type == json_type_string){
char* cmd_value;
cmd_value = json_object_get_string(val);
//g_print("VALUE:%d\n", g_utf8_collate(cmd_value, "identupdate"));
if(g_utf8_collate(cmd_value, "identupdate") == 0){
//Call "Identity Update Response"
//char return_response = p2pserver_json_identupdate_response(json_command);
}
}
}
}
*/
return;
}
If you want to see the complete code (only a couple of pages big at the time of this writing) you can go to the source code at the following link: https://github.com/Xenland/P2PCrypt-Server
Thanks for your time and help!
c passes arguments by value, not by reference. You problem is here:
void parse_json_command(char json_command, char *response){
[...]
response = "YOU KNOW";
[...]
}
char *response;
parse_json_command(req, response);
response is a uninitialized pointer to a string. You are assigning a pointer to a static string to the response pointer in the function, but that does not modify response outside of the function, it just changes response within the function. There are different ways to fix this. Probably the easiest one for a quick fix would be to change the function's prototype to return a char * instead of void:
char * parse_json_command(char json_command){
char *response;
[...]
response = "YOU KNOW";
[...]
return response;
}
char *response;
response = parse_json_command(req);
Also, the json_command argument should probably be a char * or const char *, not just a single char, if you want to pass more than a single byte there.
I am having a lot of trouble with this piece of code (I am not good at pointers :P). So here is the code.
printf("\n Enter the file name along with its extensions that you want to delete:-");
scanf("%s",fileName);
deletefile_1_arg=fileName;
printf("test\n");
result_5 = deletefile_1(&deletefile_1_arg, clnt);
if (result_5 == (int *) NULL) {
clnt_perror (clnt, "call failed");
}
else
{
printf("\n File is deleted sucessfully");
goto Menu2;
}
break;
Function that is getting called is as following.
int *
deletefile_1_svc(char **argp, struct svc_req *rqstp)
{
static int result;
printf("test2\n");
printf("%s",**argp);
if(remove(**argp));
{
printf("\nFile Has Been Deleted");
result=1;
}
return &result;
}
I am getting test2 on console but. It does not print value of argp / removes that perticular file. I am not sure what I am doing wrong. Please help me.
The argp is a pointer to a pointer char, and you are trying to use it as a pointer to char, try change your code to:
printf("%s", *argp);
You would also need to change your remove call to:
remove(*argp);
I always found drawing pictures helped understand pointers. Use boxes for memory addresses and a label for the box is the variable name. If the variable is a pointer, then the contents of the box is the address of another box (draw line to the other box).
You are using pointers when you don't need to. Your "deletefile1_svc" function doesn't manipulate the value of "argp" at all so it doesn't need a pointer-to-pointer. Plus your "result" doesn't need to be returned as a pointer since it is simply a numeric value. You also don't initialize result (it might be zero) or re-initialize it (it is static so it will remember the last value assigned to it).
int
deletefile_1_svc(const char *argp, struct svc_req *rqstp)
{
int result = 0; /* Initial value => failure */
if (remove (argp) == 0)
{
result = 1; /* 1 => success */
}
return result;
}
To call the function use:
result_5 = deletefile1_svc(filename, clnt);
if (result_5 == 0)
// Failed
else
// Success
That will make the code simpler and less prone to bugs.
I am very much stuck in the following issue. Any help is very much appreciated!
Basically I have a program wich contains an array of structs and I am getting a segmentation error when I call an external function. The error only happens when I have more than 170 items on the array being passed.
Nothing on the function is processed. The program stops exactly when accessing the function.
Is there a limit for the size of the parameters that are passed to external functions?
Main.c
struct ratingObj {
int uid;
int mid;
double rating;
};
void *FunctionLib; /* Handle to shared lib file */
void (*Function)(); /* Pointer to loaded routine */
const char *dlError; /* Pointer to error string */
int main( int argc, char * argv[]){
// ... some code ...
asprintf(&query, "select mid, rating "
"from %s "
"where uid=%d "
"order by rand()", itable, uid);
if (mysql_query(conn2, query)) {
fprintf(stderr, "%s\n", mysql_error(conn2));
exit(1);
}
res2 = mysql_store_result(conn2);
int movieCount = mysql_num_rows(res2);
// withhold is a variable that defines a percentage of the entries
// to be used for calculations (generally 20%)
int listSize = round((movieCount * ((double)withhold/100)));
struct ratingObj moviesToRate[listSize];
int mvCount = 0;
int count =0;
while ((row2 = mysql_fetch_row(res2)) != NULL){
if(count<(movieCount-listSize)){
// adds to another table
}else{
moviesToRate[mvCount].uid = uid;
moviesToRate[mvCount].mid = atoi(row2[0]);
moviesToRate[mvCount].rating = 0.0;
mvCount++;
}
count++;
}
// ... more code ...
FunctionLib = dlopen("library.so", RTLD_LAZY);
dlError = dlerror();
if( dlError ) exit(1);
Function = dlsym( FunctionLib, "getResults");
dlError = dlerror();
(*Function)( moviesToRate, listSize );
// .. more code
}
library.c
struct ratingObj {
int uid;
int mid;
double rating;
};
typedef struct ratingObj ratingObj;
void getResults(struct ratingObj *moviesToRate, int listSize);
void getResults(struct ratingObj *moviesToRate, int listSize){
// ... more code
}
You are likely blowing up the stack. Move the array to outside of the function, i.e. from auto to static land.
Another option is that the // ... more code - array gets populated... part is corrupting the stack.
Edit 0:
After you posted more code - you are using C99 variable sized array on the stack - Bad IdeaTM. Think what happens when your data set grows to thousands, or millions, of records. Switch to dynamic memory allocation, see malloc(3).
You don't show us what listsize is, but I suppose it is a variable and not a constant.
What you are using are variable length arrays, VLA. These are a bit dangerous if they are too large since they usually allocated on the stack.
To work around that you can allocate such a beast dynamically
struct ratingObj (*movies)[listSize] = malloc(sizeof(*movies));
// ...
free(movies);
You'd then have in mind though that movies then is a pointer to array, so you have to reference with one * more than before.
Another, more classical C version would be
struct ratingObj * movies = malloc(sizeof(*movies)*listsize);
// ...
free(movies);