Seg fault using struct - c

I have been writing C for approximately a week, so bear with me. I'm getting a segmentation fault error in the method assemble_url and I dont know why. Here is my code:
/** Includes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql/mysql.h>
/** Definitions */
#define MAX_OPTIONS 32
#define MAX_ARGS 32
/** Command option */
typedef struct {
char *argname;
char *value;
} command_option;
/** Command */
typedef struct {
command_option options[MAX_OPTIONS];
} command_t;
/**
* Prints the arguments passed in in a hashmap format (key => value)
*/
void populate_command(command_t *cmd,int argc,char *argv[])
{
int i,j=0;
/** Check to see if we have arguments. If argc is equal to 1 than there are no arguments besides the filename */
if(argc>1)
{
/* Start at position 1, since argv[0] is the filename being called */
for(i=1;i<argc;i++)
{
/* Head of argv array */
char *arg = argv[i];
/* Create a copy of head for traversal. */
char *c = arg;
/* traverse the char array, ensuring we arent dealing with NULL values(c!==NULL) and NULL pointers(*c!=='\0') */
while(*c != '\0' && c != NULL)
{
/* Were only concerned with parsing the flags and obtaining the flag value. */
if(strchr("-",*c))
{
char *key = c; /* Key */
char *value = argv[i+1]; /* Value */
/* ensure we have a value existent for key */
if(strchr("-",*value))
{
/** user supplied a key with no value */
break;
}
command_option *option = &cmd->options[j];
option->argname = key;
option->value = value;
j++;
/* Debug dump */
printf("arg %d: %s -> %s\n",i,option->argname,option->value);
}/* end strchr */
/** Increment the traversal array */
c++;
}/* end while loop */
}/* end forloop */
}/* endif */
}/** end print_args */
/**
* Concatenates two strings and returns the resulting concatenated string
*/
char* concatstring(char *s1,char *s2)
{
/* Allocate memory for *result. We add 1 to account for the extra byte to store the null character. Strlen accounts for all
non-null bytes, so using strlen(s1) + strlen(s2) + 1 ensures that an overflow wont occur. An overflow occurs when
the number of bytes being used (in our example, is the addition of strlen for s1 and s2) is more than the number of bytes
allocated (in our example, the number of bytes allocated to *result)*/
char *result = malloc(strlen(s1)+strlen(s2)+1);
/*Copies the C string pointed by source(s1) into the array pointed by destination(result), including the terminating null character. */
strcpy(result,s1);
/* appends a copy of the source string(s2) to the destination string(result). The terminating null character in
destination is overwritten by the first character of source, and a null-character is included at
the end of the new string formed by the concatenation of both in destination.*/
strcat(result,s2);
/* return result */
return result;
} /** end concatstring */
char* assemble_url(command_t *cmd,char *str)
{
int i,opt_len = sizeof(&cmd->options);
for(i=0;i<opt_len;i++)
{
command_option *option = &cmd->options[i];
char *key = option->argname;
char *value = option->value;
if(i==0)
{
str = concatstring(str,key);
str = concatstring(str,"=");
str = concatstring(str,value);
}
else
{
str = concatstring(str,"&");
str = concatstring(str,key);
str = concatstring(str,"=");
str = concatstring(str,value);
}
}
return str;
}
What occurs in this program is the following:
1./ User types in program name and flag options,such as the following:
program -test a -test2 b
2./ The program parses the command and populates a command struct with options. Each option has a flag(argname) and value associated to it(value)
3./ The program then tries to create a URL with those option keys and values, such as http://url/?test=a&test2=b
The program compiles but I'm still new to pointers and references (I think & is called a reference), so maybe that is why the program errors.
Any help is greatly appreciated! Also, if you see any probems or better way to handle assemble_url, please also let me know (I dont think its being handled in the best way, but like I said, I'm extremely new to C programming)
Thanks!

This initialization
int opt_len = sizeof(&cmd->options);
will give you the byte-size of a pointer &cmd->options. This makes no sense in the context of what you are trying to do.
If you want to determine the number of elements in an array (assuming it hasn't decayed to pointer), the proper technique would be
int opt_len = sizeof cmd->options / sizeof *cmd->options;
In this case opt_len will be initialized with MAX_OPTIONS value (meaning that you can just use MAX_OPTIONS in its place).

You have massive memory leaks from concatstring. Each invocation allocates a new buffer but you never bother to free them, and you loose the pointers so no chance of ever freeing that memory again.
This is not the cause of the segfault.

Because you are concatenating more than two strings it would be best if you allocated memory for all concatenations at once.
#include <stdarg.h>
#include <string>
char* stringBuilder(int count, ...)
{
va_list ap, vacnt;
int j;
int len = 1;
char* buffer;
va_start(ap, count);
#ifdef va_copy
va_copy(vacnt,ap);
#else
vacnt = ap;
#endif
for(j=0; j<count; ++j){
len+=strlen(va_arg(vacnt, char*));
}
va_end(vacnt);
buffer = (char*) malloc(len * sizeof(char));
buffer[0]=0;
for (j=0;j<count;++j) {
strcat (buffer, va_arg(ap, char*));
}
va_end(ap);
return buffer;
}
You can use it as such:
char* x = stringBuilder(4,"hello", " ", "world", "\n");
printf(x);
free(x);
Also note that both key and value must be URL-Encoded for the purposes of your application

Related

implementing a strcpy() function without using <string.h> in C

My task is like this: I should implement the strcpy function under the following constraints:
The function should use pointer expression (*(d+i))
I should implement it without using <string.h>
I'm programming in Visual Studio 2019.
I searched some source code in google and run them, but my program has a logical error. The program ends right away, each time. I don't know what I'm doing wrong.
Here's my code in Visual Studio 2019 on Windows. Please tell me what's wrong.
#include <stdio.h>
void strcpy(char*, char*);
int main()
{
char* sen1 = "Hello";
char* sen2 = "Friends";
strcpy(sen1, sen2);
printf("The result: %s\n", sen1);
return 0;
}
void strcpy(char* str1, char* str2)
{
int i = 0;
while (*(str2 + i) != '\0')
{
*(str1 + i) = *(str2 + i);
i++;
}
*(str1 + i) = '\0';
}
In addition to needing to provide writable storage for sen1, you should also check to ensure str2 != NULL in your function before dereferencing str2 (otherwise, even if you fix all other errors -- a segfault will likely result)
For example, in your code you can define a constant to use in setting the size of a sen1 array (or you can allocate storage with malloc(), calloc(), or realloc() -- save that for later). Using an array you can do, e.g.
#include <stdio.h>
#include <stdlib.h>
#define MAXC 64 /* if you need a constant, #define one (or more) */
...
int main (void)
{
char sen1[MAXC] = "Hello";
char *sen2 = "Friends";
mystrcpy (sen1, sen2);
printf ("The result: %s\n", sen1);
}
In your strcpy function, check that str2 isn't NULL before using str2 in your function, e.g.
char *mystrcpy (char *dest, const char *src)
{
char *p = dest;
if (!src || !dest) { /* ensure src or dest is not NULL */
fputs ("error: src or dest parameters NULL in mystrcpy().\n", stderr);
exit (EXIT_FAILURE);
}
do /* loop */
*p++ = *src; /* copy each char in src to dest */
while (*src++); /* (including the nul-termianting char) */
return dest; /* return pointer to dest */
}
Now you will copy your source string to your destination string in your (renamed) mystrcpy() function, receiving the results you expect:
Example Use/Output
$ ./bin/mystrcpy
The result: Friends
Look things over and let me know if you have further questions.
Two problems, at least:
String literals are not writable in C. Often the symptom is a crash (SIGSEGV).
You are not allowed to use the identifier strcpy for your own function. Use another name.
Three clean code issues, at least:
Turn int main() into int main(void) to make it properly typed.
str1 and str2 are too generic names. They don't indicate which is the source and which is the destination pointer. What about my_strcpy(char *dest, char *src)?
I'd use size_t i for the index counter instead of int, because that's the type all the string length functions and the sizeof operator return. It's also an unsigned type and can copy really long strings :-) The size_t is available after #include <stddef.h>.
You want this:
...
char* source = "Hello";
// or char source[] = "Hello";
char destination[1000]; // destination buffer long enough for playing around
my_strcpy(destination, source);
printf("%s\n", destination); // should print "Hello" if my_strcpy is corect
...
For the rest read Jens's answer.
Among the other good answers, just regarding the implementation of your strcpy function and not a detailed issue analyze of your actual code, another approach is this:
char * n_strcpy(char * dest, char const * src)
{
if (dest == NULL || src == NULL)
{
return NULL;
}
char *ptr = dest;
while ((*dest++ = *src++));
return ptr;
}

Adding to an array in main via function argument

I'm not sure if I even worded the title correctly, but basically. I want to know if there is a way to add to the buff array from the hey function using the pointers in the arguments and why does it work if it does?
buf[100].
example:
int main(){
char buf[100];
hey("320244",buf);
printf("%s", buf);
}
void hey(char* s, char* result){
/*
some code that appends to result using pointers
do some stuff with s and get the result back in buf without using return.
*/
}
I have modified your code with some comments :-
#define LEN 100 //Use a macro instead of error prone digits in code
void hey(char* s, char* result); //Fwd declaration
int main(){
char buf[LEN] = {0}; //This will initialize the buffer on stack
hey("320244",buf);
printf("%s", buf);
hey("abc", buf); //Possible future invocation
printf("%s", buf);
}
void hey(char* s, char* result){
if(strlen(result) + strlen(s) < LEN ) //This will check buffer overflow
strcat(result, s); //This will concatenate s into result
else
//Do some error handling here
}
Let's do the right thing, and use a structure to describe a dynamically allocated, grow-as-needed string:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
struct mystring {
char *ptr; /* The actual string */
size_t len; /* The length of the string */
size_t max; /* Maximum number of chars allocated for */
};
#define MYSTRING_INIT { NULL, 0, 0 }
If we want to append something to a struct mystring, we define a function that takes a pointer to the structure the function can modify. (If it only needed a char pointer instead of a structure, it'd take a char **; a pointer to a char pointer.)
void mystring_append(struct mystring *ms, const char *s)
{
const size_t slen = (s) ? strlen(s) : 0;
/* Make sure ms points to a struct mystring; is not NULL */
if (!ms) {
fprintf(stderr, "mystring_append(): No struct mystring specified; ms == NULL!\n");
exit(EXIT_FAILURE);
}
/* Make sure we have enough memory allocated for the data */
if (ms->len + slen >= ms->max) {
const size_t max = ms->len + slen + 1;
char *ptr;
ptr = realloc(ms->ptr, max);
if (!ptr) {
fprintf(stderr, "mystring_append(): Out of memory!\n");
exit(EXIT_FAILURE);
}
ms->max = max;
ms->ptr = ptr;
}
/* Append. */
if (slen > 0) {
memmove(ms->ptr + ms->len, s, slen);
ms->len += slen;
}
/* We allocated one char extra for the
string-terminating nul byte, '\0'. */
ms->ptr[ms->len] = '\0';
/* Done! */
}
The (s) ? strlen(s) : 0; expression uses the ?: conditional operator. Essentially, if s is non-NULL, the expression evaluates to strlen(s), otherwise it evaluates to 0. You could use
size_t slen;
if (s != NULL)
slen = strlen(s);
else
slen = 0;
instead; I just like the concise const size_t slen = (s) ? strlen(s) : 0 form better. (The const tells the compiler that the slen variable is not going to be modified. While it might help the compiler generate better code, it is mostly a hint to other programmers that slen will have this particular value all through this function, so they do not need to check if it might be modified somewhere. It helps code maintenance in the long term, so it is a very good habit to get into.)
Normally, functions return success or error. For ease of use, mystring_append() does not return anything. If there is an error, it prints an error message to standard output, and stops the program.
It is a good practice to create a function that releases any dynamic memory used by such a structure. For example,
void mystring_free(struct mystring *ms)
{
if (ms) {
free(ms->ptr);
ms->ptr = NULL;
ms->len = 0;
ms->max = 0;
}
}
Often, you see initialization functions as well, like
void mystring_init(struct mystring *ms)
{
ms->ptr = NULL;
ms->len = 0;
ms->max = 0;
}
but I prefer initialization macros like MYSTRING_INIT, defined earlier.
You can use the above in a program like this:
int main(void)
{
struct mystring message = MYSTRING_INIT;
mystring_append(&message, "Hello, ");
mystring_append(&message, "world!");
printf("message = '%s'.\n", message.ptr);
mystring_free(&message);
return EXIT_SUCCESS;
}
Notes:
When we declare a variable of the structure type (and not as a pointer to the structure, i.e. no *), we use . between the variable name and the field name. In main(), we have struct mystring message;, so we use message.ptr to refer to the char pointer in the message structure.
When we declare a variable as a pointer to a structure type (as in the functions, with * before the variable name), we use -> between the variable name and the field name. For example, in mystring_append() we have struct mystring *ms, so we use ms->ptr to refer to the char pointer in the structure pointed to by the ms variable.
Dynamic memory management is not difficult. realloc(NULL, size) is equivalent to malloc(size), and free(NULL) is safe (does nothing).
In the above function, we just need to keep track of both current length, and the number of chars allocated for the dynamic buffer pointed to by field ptr, and remember that a string needs that terminating nul byte, '\0', which is not counted in its length.
The above function reallocates only just enough memory for the additional string. In practice, extra memory is often allocated, so that the number of reallocations needed is kept to a minimum. (This is because memory allocation/reallocation functions are considered expensive, or slow, compared to other operations.) That is a topic for another occasion, though.
If we want a function to be able to modify a variable (be that any type, even a structure) in the callers scope -- struct mystring message; in main() in the above example --, the function needs to take a pointer to variable of that type, and modify the value via the pointer.
The address-of operator, &, takes the address of some variable. In particular, &message in the above example evaluates to a pointer to a struct mystring.
If we write struct mystring *ref = &message;, with struct mystring message;, then message is a variable of struct mystring type, and ref is a pointer to message; ref being of struct mystring * type.
If I have understood you correctly you mean the following
#include <string.h>
//...
void hey(char* s, char* result)
{
strcpy( result, s );
}
Here is a demonstrative program
#include <stdio.h>
#include <string.h>
void hey( const char* s, char* result);
int main(void)
{
char buf[100];
hey( "320244", buf );
printf( "%s\n", buf );
return 0;
}
void hey( const char* s, char* result )
{
strcpy( result, s );
}
Its output is
320244
If the array buf already stores a string then you can append to it a new string. For example
#include <string.h>
//...
char buf[100] = "ABC";
strcat( buf, "320244" );
Take into account that the function hey should be declared before its usage and according to the C Standard the function main shall be declared like
int main( void )

inverse String in c

i've done a function that inverse a String(array of character) given in parameter , but it's not working , any idea why ?
I'm getting something like this : æIGt(Kt$0#
thanks you
#include <stdio.h>
#include <string.h>
char *
inverse(char *s)
{
int i, taille = strlen(s);
char r[taille];
for (i = 0 ; i < taille ; i++)
{
r[i] = s[taille - i - 1];
}
r[i] = '\0';
return r;
}
int
main()
{
char s[] = "kira";
char *r = inverse(s);
printf("%s",r);
return 1;
}
You are returning a pointer to a local variable. That variable gets destroied when the function inverse returns, so accessing the pointer after the function exits will return invalid data.
It's slightly hard to tell from you question, because you haven't given any outputs, but my best guess is that it's because your returning a pointer to an item on the stack, which will get over-written by the next call, in your case printf. You need to pass inverse a place to put its answer. Try this instead:
#include <stdio.h>
#include <string.h>
void inverse(char *s, char *r)
{
int i,taille=strlen(s);
for(i=0;i<taille;i++)
{
r[i]=s[taille-i-1];
}
r[i]='\0';
}
int main()
{
char s[] = "kira";
char r[sizeof(s)];
inverse(s, r);
printf("%s",r);
return 1;
}
Another standard approach to reversing a string uses pointers to work from both the beginning and end of the string swapping two characters with each iteration. It swaps the original string in place (make a copy if you need to preserve the original, or pass a second string and place the reversed string in there)
/** strrevstr - reverse string, swaps 2 chars per-iteration.
* Takes valid string and reverses, original is not preserved.
* If 's' is valid and non-empty, returns pointer to 's',
* returns NULL otherwise.
*/
char *strrevstr (char *s)
{
if (!s || !*s) { /* validate string is not NULL and non-empty */
printf ("strrevstr() error: invalid string\n");
return NULL;
}
char *begin = s; /* pointers to beginning and end, and tmp char */
char *end = begin + strlen (s) - 1;
char tmp;
while (end > begin) /* swap both beginning and end each iteration */
{
tmp = *end;
*end-- = *begin;
*begin++ = tmp;
}
return s;
}
As you can tell, there are a number of ways to approach the problem, with this and the other answers provided, you should be able to tailor a solution to meet your needs.
There are advantages and disadvantages to every approach. There is nothing wrong with dynamically allocating a new block of memory to hold the reversed string, it just adds an additional responsibility to (1) preserve a pointer to the starting address for the new block so (2) it can be freed when no longer needed. If you need to preserve the original string, passing a pointer to an character array of sufficient size to hold the reversed string is another option preserve the original.
Look over all the answers and let me know if you have any questions.

Change string with malloc in other function

how can I change string in other function when I am using malloc?
in main:
char *myString;
changeString(myString);
changeString(char *myString){
myString = malloc((size) * sizeof(char));
myString[1] = 'a';
}
Thank you
Parameters in C are passed by value. So to modify a variable within a function, you'll have to pass the pointer to it. For example, int * to int, and char ** to char *.
void changeString(char **myString){
// free(*myString); // add when myString is allocated using malloc()
*myString = malloc(2);
(*myString)[0] = 'a';
(*myString)[1] = '\0';
}
Allocate memory in main, then pass a pointer to start of allocated memory to the function.
Also pass a variable containing the size of the allocated memory to the function, so that you can ensure that the new text does not overflow the allocated memory.
The modified string is available from main.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void changeString(char *stringptr, int sz);
int main(void)
{
const int a_sz = 16;
/* allocate memory for string & test successful allocation*/
char *myString = malloc(a_sz);
if (myString == NULL) {
printf("Out of memory!\n");
return(1);
}
/* put some initial characters into String */
strcpy(myString, "Nonsense");
/* print the original */
printf("Old text: %s\n", myString);
/* call function that will change the string */
changeString(myString, a_sz);
/* print out the modified string */
printf("New text: %s\n", myString);
/* free the memory allocated */
free(myString);
}
void changeString(char *stringptr, int sz)
{
/* text to copy into array */
char *tocopy = "Sense";
/* only copy text if it fits in allocated memory
including one byte for a null terminator */
if (strlen(tocopy) + 1 <= sz) {
strcpy(stringptr, tocopy);
}
}

Assigning a char array to a char*

I'm trying to write a function that prefixes a string with its length. I can't seem to assign a char[] to a char *. Mysteriously, if I print out some debugging code before the assignment, it works.
char *prefixMsgWLength(char *msg){
char *msgWLength;
int msgLength = strlen(msg);
if (msgLength == 0){
msgWLength = "2|";
}
else{
int nDigits = floor(log10(abs(msgLength))) + 1;
int nDigits2 = floor(log10(abs(msgLength + nDigits + 1))) + 1;
if (nDigits2 > nDigits){
nDigits = nDigits2;
}
msgLength += nDigits + 1;
char prefix[msgLength];
sprintf(prefix, "%d|", msgLength);
strcat(prefix, msg);
// if I uncomment the below, msgWLength is returned correctly
// printf("msg: %s\n", prefix);
msgWLength = prefix;
}
return msgWLength;
}
The problem in your code is
msgWLength = prefix;
here, you're assigning the address of a local variable (prefix) to the pointer and you try to return it.
Once the function finishes execution, the local variables will go out of scope and the returned pointer will be invalid.
You need to make prefix as a pointer and allocate memory dynamically, if you want it to retain it's existence after returning from the function.
String reallocation to the exact length can be very cumbersome in C. You'd probably be much better off just using a sufficiently large buffer. Here, I use limits.h to determine the size of a line buffer according to the system (LINE_MAX):
#include <stdio.h>
#include <limits.h>
#include <string.h>
int main()
{
/* Our message */
char const msg[] = "Hello, world!";
/* Buffer to hold the result */
char buffer[LINE_MAX];
/* Prefix msg with length */
snprintf(buffer, LINE_MAX, "%lu|%s", strlen(msg)+1, msg);
/* Print result */
printf("%s\n", buffer);
return 0;
}

Resources