mysql_init overwriting memory space - c

When I call mysql_init(mysql);, it is overwriting a char array. I do not understand what I am doing wrong. My code:
void prepare_mysql(MYSQL *mysql) {
mysql_library_init(0, NULL, NULL);
mysql_init(mysql);
}
void get_uid(char *src, char *dst) {
int i, len, count = 0;
len = strlen(src);
for(i = 0; i != len; i++) {
if(src[i] == '-') { // iterate until a - sign is found
break;
}
dst[count] = src[i]; // save char into dst
count++;
}
dst[count] = '\0'; // add null char at the end of char array, otherwise everything will explode...
// dst is now: 389302
}
int main(int argc, char *argv[]) {
// argv[1] is for example: 389302-8232
char uid;
get_uid(argv[1], &uid);
printf("uid = %s\n", &uid); // prints: 389302 (correct)
MYSQL conn;
prepare_mysql(&conn);
printf("uid = %s\n", &uid); // prints: 3 (the first char only.. why?)
mysql_close(&conn);
mysql_library_end();
return 0;
}
If I call the get_uid function after I call mysql_init, I cannot call mysql_close(&conn) because I get a Segmentation fault. Please help, I cannot understand..
Edit:
I have added this in main:
char *uid = malloc(strlen(argv[1]));
And later in main, I call free(uid);. Now it seems to be printing correctly everywhere before I call free.

You don't have a char array - uid is only a char.

Related

Does returning a pointer from a function make it invalid to reallocate?

So I'm currently trying to write a C program to track the longest word(s) from argv.
It's been going great! Until I tried to reallocate a character double pointer, it seems to think it's an invalid pointer.
The exact error I'm getting is;
realloc(): invalid pointer
fish: Job 1, './longest-strings.o hello...' terminated by signal SIGABRT (Abort)
I'm creating this double character pointer through the return of a function, is this possibly the error? I'm pretty sure my use of realloc is correct, and I can't quite seem to trace the issue.
Any help would be massively appreciated!
/*
* Author: Smallblue2
* Description: Program finds the longest word in an input string
*
* Input: A string from cmd line
* Output: The longest word in a string
*/
// Header files
#include <stdio.h>
#include <stdlib.h>
// Function prototypes
int stringLength(char *string);
void longestWords(char **strings, int amt);
char **reset(char *string);
void display(char **longest, int len_array);
// Main function
int main(int argc, char **argv)
{
char **strings = &*(argv + 1);
longestWords(strings, argc - 1);
return 0;
}
// Find the length of a string
int stringLength(char *string)
{
int length = 0;
while (*string != '\0')
{
length++;
string++;
}
return length;
}
// Finds the longest word(s) from argv
void longestWords(char **strings, int amt)
{
// Set up variables & pointers
int len_array = 1;
// Assign the first string to be the longest
char **longest = reset(*(strings));
int longest_len = stringLength(*(longest));
int length = 0;
// Loop through the rest of the strings
for (int i = 1; i < amt; i++)
{
// Find the length of the current string
length = stringLength(*(strings + i));
// If it is larger, reset the longest array and place the
// new string inside
if (length > longest_len)
{
longest_len = length;
longest = reset(*(strings + i));
len_array = 1;
// Else, expand the longest array's memory and add the
// additional string inside
} else if (length == longest_len) {
len_array++;
char **temp_longest = (char **)realloc(longest, len_array * sizeof(char *));
if (!longest)
{
printf("Error: Memory allocation failed!\n");
free(longest);
return;
}
longest = temp_longest;
*(longest + len_array - 1) = *(strings + i);
}
}
// Display the longest word(s)
display(longest, len_array);
free(longest);
longest = NULL;
return;
}
// Resets the longest word array
char **reset(char *string)
{
char **longest = (char **)malloc(sizeof(char *));
if (!longest)
{
printf("Error: Memory Allocation Failed!\n");
return NULL;
}
longest = &string;
return longest;
}
// Displays the longest word(s)
void display(char **longest, int len_array)
{
for (int i = 0; i < len_array; i++)
{
printf("%s\n", *(longest + i));
}
return;
}
I've tried to use both calloc and malloc, I tried executing the script where realloc wouldn't occur and then apparently free() believes there's an invalid pointer too. Really lost here.
Here are the two minimal changes:
stringLength should handle a NULL pointer.
int stringLength(char *string)
{
int length = 0;
while (string && *string != '\0')
{
length++;
string++;
}
return length;
}
Or perhaps:
#include <string.h>
size_t stringLength(char *string)
{
return string ? strlen(string) : 0;
}
reset() leaks the memory you just allocated, and you don't want to take the address of an argument which is out of scope when the function returns. Not entirely sure what the point of the function is but try this instead:
char **reset(char *string)
{
char **longest = malloc(sizeof(char *));
if (!longest)
{
printf("Error: Memory Allocation Failed!\n");
return NULL;
}
*longest = string;
return longest;
}
and example output:
$ ./a.out hello...
hello...
./a.out hello world!
world!

realloc, two dimention allocation, leak and errors in valgrind

I wrote a program to split given string according to certain delimiter. Everything works fine but there are leak and error in valgrind.
split algorithm is correct.
substr works fine.
My program:
#include <stdio.h>
#include <stdlib.h>
char** split(const char*, char, int*);
char* substr(const char*, int, int);
void freepath(char**, int);
int main(void) {
char *str = "home///ubuntu//Desktop";
char **path = NULL;
int size = 0;
path = split(str, '/', &size);
freepath(path, size);
return 0;
}
char** split(const char *str, char c, int *size) {
char **path = NULL;
const char *save = str;
int from=-1, i;
if(str == NULL)
return NULL;
for(i=0 ; 1; ++i) {
if(*str == '\0') {
if(from != -1) {
++(*size);
path = (char**)realloc(path, (sizeof(char**) *(*size)));
*(path+(*size)-1) = substr(save, from, i);
}
break;
}
if(*str != '/') {
if(from == -1)
from = i;
}
else {
if(from != -1) {
++(*size);
path = (char**)realloc(path, (sizeof(char)*(*size)));
*(path+(*size)-1) = substr(save, from, i);
}
from = -1;
}
++str;
}
return path;
}
void freepath(char **path, int size) {
int i=0;
for(i=0; i<size; ++i) {
free(*(path+i));
*(path+i) = NULL;
}
free(path);
path = NULL;
}
char* substr(const char *src, int m, int n)
{
int len = n - m;
char *dest = (char*)malloc(sizeof(char) * (len + 1));
for (int i = m; i < n && (*(src + i) != '\0'); i++)
{
*dest = *(src + i);
++dest;
}
*dest = '\0';
return dest - len;
}
Valgrind output:
What should be the reason ? , I really stuck with it !
clang analyser has found 4 suspected points in your code:
1.
char *str = "home///ubuntu//Desktop";
needs const in front of char (pointer to const).
2.
char** split(const char *str, char c, int *size) {
contains an unused parameter (c).
3.
path = (char**)realloc(path, (sizeof(char**) *(*size)));
clang-analyser does not like char** as the argument of sizeof, replacing it with char* removes the warning.
4.
path = (char**)realloc(path, (sizeof(char)*(*size)));
The same warning as in 3. Errr, no, not the same. Bingo! Replace char inside sizeof with char* and you're back home.
One final remark. When you use valgrind, always add debugging information to the compiled code, that is, add -g to the compiler command-line options (gcc, clang, etc.). This will give you the information about the exact lines numbers in your source code corresponding to the places where the problem was spotted by valgrind. My screenshot of your program under valgrind contains more information than yours:
Please notice that valgrind correctly identifies line 44 as the line with the buggy memory allocation (or line 45 with a buggy usage of the buffer allocated at line 44. Both options are a priori possibly correct).

Pointer to string not incrementing (C programming)

I have two string shown below:
char code *text_to_compare = "TesT";
char code *dictionary = "TesTT,Tes,Tes,TesT.";
In a part of the program I used the following code where it increments the pointers for both strings to point to the next characters.
ch_A = text_to_compare[i++];
ch_B = dictionary[j++];
Why is pointer j being incremented but pointer i is remaining as it was?
Thanks in advance.
EDIT: Below is the full code. The aim of this project is to compare a string with a list of words. Integer i is not incrementing only after the program enters the else statement.
#include <string.h>
char code *text_to_compare = "TesT";
char code *dictionary = "TesTT,Tes,Tes,TesT.";
int bring_characters(char pdata *, char pdata *, char ch_A, char ch_B, char i,
char j);
void main(void) {
unsigned char ch_A;
unsigned char ch_B;
unsigned char i = 0;
unsigned char j = 0;
char pdata N1;
char pdata N2;
int result;
ch_A = text_to_compare[i]; // take a caharacter from the text
ch_B = dictionary[j];
result = bring_characters(&N1, &N2, ch_A, ch_B, i, j);
if (result == 0) {
while (1)
;
}
else {
while (1)
;
}
while (1)
;
}
int bring_characters(char pdata *N1, char pdata *N2, char ch_A, char ch_B,
char i, char j) {
do {
if (ch_A == ch_B) {
ch_A = text_to_compare[i++]; // take a caharacter from the text
ch_B = dictionary[j++];
if ((ch_A == '\0') && ((ch_B == ',') || (ch_B == '.'))) {
while (1)
; // load idata-------------------------------------------------------------------------------------------------
}
}
else {
i = 0; // refresh pointer
ch_A = text_to_compare[i]; // take a caharacter from the text
ch_B = dictionary[j++];
}
} while (ch_B != '.');
return (0);
}
Whew, there's a lot going on here! Now that you've added the full code it looks like in your attempt to move on to the next word you have prevented yourself from moving on.. you'll need to do some major revisions to get this guy working.
The first thing you need to do is figure out how you would do this on paper, then step by step try to reproduce that in your code.
Here's a function to kickstart you:
int find_next_match(char toFind, int startingPosition, char* mainString){
int counter = startingPosition;
char buf = mainString[counter];
while(buf != NULL){
if (buf == toFind){
return counter;
}
counter++;
buf = mainString[counter];
}
return -1; //error
}
You can use something like this to find the next instance of the first character in your string, then you can implement a loop to determine if that is a match.
Good luck, you can do it!

C reference gone after for loop

i got a problem with my C code.
int split(char* source, char*** target, char* splitChar) {
int i;
int currentLength;
int splitCharPosition;
char* currentSubstring = source;
int splitCount = charcount(source, splitChar) + 1;
*target = (char**) malloc(splitCount * sizeof(char**));
for(i=0;i<splitCount;i++) {
splitCharPosition = indexOf(currentSubstring, splitChar);
substring(currentSubstring, target[i], 0, splitCharPosition);
currentLength = strlen(currentSubstring);
substring(currentSubstring, &currentSubstring, splitCharPosition + 1, curr entLength-splitCharPosition);
}
return splitCount;
}
The problem is that if I use the Debugger, the pointer to splitChar is set to 0x0 after the first run of the for loop.
Does anybody know why it is set to 0x0?
EDIT:
int indexOf(char* source, char* template) {
int i;
int j;
int index;
for (i = 0; source[i]; i++) {
index = i;
for (j = 0; template[j]; j++) {
if (source[i + j] != template[j]) {
index = -1;
break;
}
}
if (index != -1) {
return index;
}
}
return -1;
}
EDIT2:
int charcount(char* source, const char* countChar) {
int i;
int count = 0;
for(i=0;source[i];i++) {
if(source[i] == countChar[0]) {
count++;
}
}
return count;
}
EDIT3:
char* substring(char* source, char** target, int start, int length) {
*target = (char*) malloc(length + 1);
strncpy(*target, source + start, length);
target[length] = '\0';
return *target;
}
EDIT4:
I just noticed that if I add
char* sndfpgjps = splitChar;
to my split() code it does not delete the reference. Anyone know why?
This line:-
substring(currentSubstring, &currentSubstring, splitCharPosition + 1, curr entLength-splitCharPosition);
... will cause a memory leak, as well as being incredibly inefficient. The old substring is left dangling. and never freed.
It would be much better to write
currentSubString += splitCharPosition + 1;
I don't think that's the problem, but it's a problem.
Also, as you're using C library functions like strlen(), why aren't you using strtok or better yet, strtok_r?
I have some reservations about the code, but this works cleanly under valgrind (no leaks, no abuse). I've left the sub-functions largely unchanged except that constant strings are marked constant. The code in split() has been simplified. As I noted in a comment, I suggest writing the main split() function so that you have a local char **string_list; which you allocate and fill. Then, when you're about to return, you assign *target = string_list;. This will make it easier for you to understand what's going on. Triple indirection is nasty. You can justify it here (just), but minimize the time you spend working with triple pointers. The revision adopts that strategy.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int split(const char *source, char ***target, const char *splitStr);
static int
indexOf(const char *source, const char *template)
{
int i;
int j;
int index;
for (i = 0; source[i]; i++)
{
index = i;
for (j = 0; template[j]; j++)
{
if (source[i + j] != template[j])
{
index = -1;
break;
}
}
if (index != -1)
return index;
}
return -1;
}
static int
charcount(const char *source, const char *countChar)
{
int count = 0;
for (int i = 0; source[i]; i++)
{
if (source[i] == countChar[0])
count++;
}
return count;
}
static char *
substring(const char *source, int start, int length)
{
char *target = (char *)malloc(length + 1);
if (target != 0)
{
memmove(target, source + start, length);
target[length] = '\0';
}
return target;
}
int
split(const char *source, char ***target, const char *splitStr)
{
int splitCount = charcount(source, splitStr) + 1;
char **result = (char **)malloc(splitCount * sizeof(*result));
if (result == 0)
return -1;
int splitLength = strlen(splitStr);
char **next = result;
const char *currentSubstring = source;
for (int i = 0; i < splitCount; i++)
{
int splitCharPosition = indexOf(currentSubstring, splitStr);
if (splitCharPosition < 0)
break;
*next++ = substring(currentSubstring, 0, splitCharPosition);
currentSubstring += splitCharPosition + splitLength;
}
*next++ = substring(currentSubstring, 0, strlen(currentSubstring));
*target = result;
return (next - result); /* Actual number of strings */
}
static void print_list(int nstrings, char **strings)
{
for (int i = 0; i < nstrings; i++)
{
if (strings[i] != 0)
printf("%d: <<%s>>\n", i, strings[i]);
}
}
static void free_list(int nstrings, char **strings)
{
for (int i = 0; i < nstrings; i++)
free(strings[i]);
free(strings);
}
int main(void)
{
const char source[] = "This is a string; it is really!";
char **strings;
int nstrings;
nstrings = split(source, &strings, " ");
printf("Splitting: <<%s>> on <<%s>>\n", source, " ");
print_list(nstrings, strings);
free_list(nstrings, strings);
nstrings = split(source, &strings, "is");
printf("Splitting: <<%s>> on <<%s>>\n", source, "is");
print_list(nstrings, strings);
free_list(nstrings, strings);
return 0;
}
Note that in the second example, charcount() returns 6 but there are only 4 strings. This caused a late adjustment to the source code. (You could realloc() the result so it is exactly the right size, but it probably isn't worth worrying about unless the discrepancy is really marked — say 'more than 10 entries'.) The error handling is not perfect; it doesn't access invalid memory after failure to allocate, but it doesn't stop trying to allocate, either. Nor does it report failures to allocate individual strings — it does for failure to allocate the array of pointers.
I'd probably avoid the triple pointer by creating a structure:
typedef struct StringList
{
size_t nstrings;
char **strings;
} StringList;
You can then pass a pointer to one of these into split(), and into the utility functions such as free_list() and print_list(). The free_list() function would then modify the structure so that both elements are zeroed after the data pointed at by the structure is freed.
I'd also be tempted to use a different implementation of indexOf():
int indexOf(const char *haystack, const char *needle)
{
const char *pos = strstr(haystack, needle);
if (pos != 0)
return (pos - haystack);
return -1;
}
I do not know what substring does, nor what signature it has, but in the line
substring(currentSubstring, target[i], 0, splitCharPosition);
target[i] is only defined for i==0. I believe you wanted to write
substring(currentSubstring, (*target)[i], 0, splitCharPosition);
See if your debugger also supports data breakpoints, i.e. break if some place in memory is modified. Then place one at the actual address of splitChar, and another at the address it points to. (Since you didn't specify whether the pointer is null or points to nil.) See where it breaks. It may be that it is a completely unrelated place; that would indicate a buffer overflow.
Also, you could make at least splitChar a pointer to const. You don't actually want to modify it, right? Better idea, make it a char, not a pointer, since its name suggests that there is only one character on which you split, not a string.
The first call to substring does not look correct:
substring(currentSubstring, target[i], 0, splitCharPosition);
I suspect it should be something like the following where it indexes the actual memory that was allocated:
substring(currentSubstring, &((*target)[i]), 0, splitCharPosition);
You first need to get the value that target points at (*target) and then index off of that and pass the address of that array location.

Null terminating char pointer

I am completely newbie in C.
I am trying to do simple C function that will split string (char array).
The following code doesn't work properly because I don't know how to terminate char array in the array. There are to char pointers passed in function. One containing original constant char array to be split and other pointer is multidimensional array that will store each split part in separate char array.
Doing the function I encountered obviously lots of hustle, mainly due to my lack of C experience.
I think what I cannot achieve in this function is terminating individual array with '\0'.
Here is the code:
void splitNameCode(char *code, char *output);
void splitNameCode(char *code, char *output){
int OS = 0; //output string number
int loop;
size_t s = 1;
for (loop = 0; code[loop]; loop++){
if (code[loop] == ':'){
output[OS] = '\0'; // I want to terminate each array in the array
OS ++;
}else {
if (!output[OS]) {
strncpy(&output[OS], &code[loop], s);
}else {
strncat(&output[OS], &code[loop], s);
}
}
}
}
int main (int argc, const char * argv[]) {
char output[3][15];
char str[] = "andy:james:john:amy";
splitNameCode(str, *output);
for (int loop = 0; loop<4; loop++) {
printf("%s\n", output[loop]);
}
return 0;
}
Here is a working program for you. Let me know if you need any explanation.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void splitNameCode(char *code, char **output) {
int i = 0;
char* token = strtok(code, ":");
while (token != NULL) {
output[i++] = token;
token = strtok(NULL, ":");
}
}
int main (int argc, const char *argv[]) {
char* output[4];
char input[] = "andy:james:john:amy";
splitNameCode(input, output);
for (int i = 0; i < 4; i++) {
printf("%s\n", output[i]);
}
return 0;
}
If I understand your intent correctly, you are trying to take a string like andy:james:john:amy and arrive at andy\0james\0john\0amy. If this is the case, then your code can be simplified significantly:
void splitNameCode(char *code, char *output){
int loop;
strncpy(code, output, strlen(code));
for (loop = 0; output[loop]; loop++){
if (output[loop] == ':'){
output[loop] = '\0'; // I want to terminate each array in the array
}
}
}

Resources