-1

I want to store a string to a char array inside a structure and when I access the char array I want the result to be displayed along with the value from the global variable errCode. When I access the errDesc member of the structure then I want the result to be "Error detected with error code 0xA0B0C0D0", but since using strcpy copies the string as it is I am getting a result "Error detected with error code %08lx" . Here is a sample code which replicates my issue:

int errCode = 0xA0B0C0D0;

void function(errpacket* ptr, int a, char* errString, ...);

typedef struct{
    int err;
    char errDesc;
}errpacket;

int main(){
    errpacket* a;
    void function(a, 10, "Error detected with error code %08lx", errCode);

    return 0;
}

void function(errpacket* ptr, int a, char* errString, ...){
    ptr->err = a;
    strcpy(&ptr->errDesc, errString);
}

If my implementation is incorrect, please suggest me a way to do what I intend to. Also please point out the mistakes in the above code.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Rookie_Coder2318
  • 81
  • 1
  • 1
  • 7

4 Answers4

1
  1. you have to typedef the struct errpacket before declaration of function(...)

  2. Variable a in function main() is only a pointer. You'll get a segmentation fault inside function if you try to write to an uninitialized pointer.

The member errDesc will only hold ONE char, not a string or char array.

Try this...

int errCode = 0xA0B0C0D0;

typedef struct {
    int err;
    char* errDesc;   
} errpacket;

void function (errpacket* ptr, int a, char* errString, ...);

int main () {
    errpacket a;
    function(&a, 10, "Error detected with error code %08lx", errCode);
    return 0;
}

void function (errpacket* ptr, int a, char* errString, ...) {
    ptr->err = a;
    ptr->errDesc = strdup( errString);
}
  • won't strdup() just duplicate the string as it is ? How about the sprintf() function , cause I want the value A0B0C0D0 added to the string. – Rookie_Coder2318 Nov 15 '16 at 16:55
0

You can't use a single char variable to hold an entire string.

What you can do is declare errDesc to be either an array of fixed length (if you know the maximum number of characters that an error description can contain), or a pointer that is allocated dynamically with malloc and later freed with free.

Array case:

#define MAX_ERR_STRING_SIZE 500

typedef struct 
{
    int err;
    char errDesc[MAX_ERR_STRING_SIZE];
} errpacket;

// You can now use strcpy() to copy to errpacket::errDesc assuming none of the error strings exceed MAX_ERR_STRING_SIZE

Dynamic memory:

typedef struct 
{
    int err;
    char *errDesc;
} errpacket;

// Take note of the new parameter: int errStringLength, 
void function(errpacket* ptr, int a, char* errString, int errStringLength, ...){
    ptr->err = a;
    ptr->errDesc = malloc((errStringLength + 1) * sizeof(char));
    if(ptr->errDesc == NULL)
    {
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    strcpy(&ptr->errDesc, errString);
}

After you are done using ptr you will need to call free(ptr->errDesc); to de-allocate the string.

Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
0

try this fix:

#include <stdarg.h> //to be added for vsprintf use

int errCode = 0xA0B0C0D0;

void function(errpacket* ptr, int a, char* errString, ...);

typedef struct{
    int err;
    char *errDesc;
}errpacket;

int main(){
    errpacket a; //you need allocate memory if you use a pointer here
    void function(&a, 10, "Error detected with error code %08lx", errCode);

    return 0;
}

void function(errpacket* ptr, int a, char* errString, ...){
    ptr->err = a;
    ptr->errDesc = malloc(strlen(errString)+1);
    memset(ptr->errDesc, 0, strlen(errString)+1);
    /*if(ptr->errDesc != NULL)
    {
        strcpy(ptr->errDesc, errString);
    }*/
   // use like following if you want use a formatted string
   if(ptr->errDesc != NULL)
   {
        va_list args;
        va_start (args, errString);
        vsprintf (ptr->errDesc, errString, args);
        va_end (args);
   }
}
developer
  • 4,744
  • 7
  • 40
  • 55
0

I don't think you really want a function with variable arguments, like printf. The solution below just expects the arguments you use in the end. Note that I do not use a user-supplied format string; that is considered a security risk. I also used snprintf (instead of the simple sprintf) in order to protect against error messages which are longer than the array size in the struct. The array size is a define so that it can be changed easily.

Specific fixes:

  • Proper declaration order (define the struct type before it's used)
  • Define an actual error packet object (and not just an uninitialized pointer to one)
  • Provide actual memory in the error packet for the message
  • Provide a print function for error packets
  • Do not let the user code specify printf formats; print user supplied strings with a length protected %s format specifier.
  • Do not use a variable argument function (whose excess arguments were not evaluated anyway); just declare the needed arguments explicitly.

.

#include<stdio.h>

int errCode = 0xA0B0C0D0;

#define MAX_ERRDESC_LEN 80 // avoid literals

typedef struct{
    int err;
    char errDesc[MAX_ERRDESC_LEN]; // provide actual space for the message
}errpacket;

void printErrPack(FILE *f, errpacket *ep){
    fprintf(f, "Error packet:\n");
    fprintf(f, "     err  = 0x%x:\n", ep->err);
    fprintf(f, "     desc = ->%s<-\n", ep->errDesc);
}

// Standard function with fixed argument count and types
void function(errpacket* ptr, int errNo, char* errString, int errCodeArg){
    ptr->err = errNo;

    // snprintf "prints" into a string
    snprintf(   ptr->errDesc,    // print destination
                MAX_ERRDESC_LEN, // max length, no buffer overflow
                "%s with error code %x", // do not use user string as format
                errString,       // user supplied string, printed via %s
                errCodeArg  );
}

int main(){
    errpacket a; // define an actual object, not a pointer

    // pass the address of the object a
    function(&a, 0xdead, "Error detected ", errCode);

    printErrPack(stdout, &a);
    return 0;
}
Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62