Passing char* to a function in combination with memcpy - c

usually a basic question, but maybe I am just too stupid. I try to pass an char * as output trought the parameter of a function. Inside the function I create a temporary char * which I want to memcpy to the address I've passed. Here is the code:
#define BLOCKSIZE=1024
int myFunction(char *s, char **out) {
int i = strlen(s);
*out = (char *)malloc(BLOCKSIZE);
char tmp[BLOCKSIZE];
strcpy(tmp, s);
tmp[++i] = 0x0f;
for(int i=strlen(s);i < BLOCKSIZE; i++) {
tmp[i] = 0xcc;
}
memcpy(*out, tmp, BLOCKSIZE);
return 0;
}
int main() {
char *s = "Hello World";
char *o = (char *)malloc(BLOCKSIZE);
myFunction(s, &o);
}
The problem is, the stack gets corrupted after it jumps out of the function myFunction..
Is there another way to do it?
Thank you in advance!
Best,
Update: Problem solved
The for loop part i < BLOCKSIZE must be changed to i < (BLOCKSIZE - 1).

Your first problem is that you malloc twice, before and in the function. The malloc outside the call (second line of main) is leaked.
The second problem (and this tells me you didn't even compile the code) is that you use i before defining it.

Related

How can I free memory and at the same time return a pointer?

I have these functions
char *hash(char *stringa, char *tipohash) {
if (strcmp(tipohash, "md5") == 0) {
stringa = md5(stringa);
}
return stringa;
}
char *md5(char *stringa) {
unsigned char risultato[MD5_DIGEST_LENGTH];
int i;
char *hashfinale = malloc(sizeof(char) * MD5_DIGEST_LENGTH * 2);
MD5((const unsigned char *)stringa, strlen(stringa), risultato);
for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
sprintf(hashfinale + 2 * i, "%02x", risultato[i]);
}
return (char *)hashfinale;
}
How I can return (char *)hashfinale doing the free without losing the value of the string?
This is the caller
char *hashlinea = hash(stringa, hashType);
There are basically two ways to solve the problem, and none of them involves your code calling free.
The first way is to just do nothing different from now, except to add documentation so the user of your hash function knows that the code must call free on the returned pointer:
// This is the code using your function
char *hashlinea = hash(stringa,hashType);
// Some code using hashlinea
free(hashlinea);
The second way is to pass a pointer to an existing array, and your code use that array instead of allocating it using malloc:
char hashlinea[MD5_DIGEST_LENGTH*2];
hash(stringa, hashType, hashlinea);
For this your hash function needs to pass on the third argument to the md5 function, which should use it instead of allocating memory:
char *md5(char *stringa, char *hashfinale){
unsigned char risultato[MD5_DIGEST_LENGTH];
int i;
// No memory allocation here
MD5((const unsigned char *)stringa, strlen(stringa), risultato);
for(i = 0; i < MD5_DIGEST_LENGTH; i++) {
sprintf(hashfinale + 2*i,"%02x",risultato[i]);
}
return hashfinale;
}
It is not possible. IMO it is better to pass the pointer to the buffer. The caller will be responsible for the memory management
char *md5(char *stringa, char *hashfinale){
...
}
There is a problem in your md5 function: the size allocated for the MD5 hash must be one byte longer for the null terminator:
char *hashfinale = malloc(sizeof(char) * (MD5_DIGEST_LENGTH * 2 + 1));
Note that in C (and C++) sizeof(char) is 1 by definition, so you could just write:
char *hashfinale = malloc(MD5_DIGEST_LENGTH * 2 + 1);
Regarding your question, hash returns either its argument or an allocated object. This is a problem for memory management, as yo may not know later in the program if the return value must be freed or not. Passing the destination array for the hash string is a better alternative, otherwise you should duplicate the string so the return value of hash can be unconditionally freed:
char *md5(const char *stringa) {
unsigned char risultato[MD5_DIGEST_LENGTH];
int i;
char *hashfinale = malloc(MD5_DIGEST_LENGTH * 2 + 1);
MD5((const unsigned char *)stringa, strlen(stringa), risultato);
for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
sprintf(hashfinale + 2 * i, "%02x", risultato[i]);
}
return hashfinale;
}
// always free the return value
char *hash(const char *stringa, const char *tipohash) {
if (!strcmp(tipohash, "md5")) {
return md5(stringa);
} else {
return strdup(stringa);
}
}

Return for type void function

I'm trying to program a function that allows me to locate a substring "from" in a string "src", and replace the "from" substring with the "to" substring in all cases, and output the new string through "dest"; however I think my code looks a bit iffy, and I do not understand (conceptually) how I would return an output with dest, given that the output is of type void. I was wondering if someone could offer some assistance?
for example:
find_replace("pooppoop poop", "poo", "hel", dest) should return
"helphelp help"
thank you!
void find_replace(char* src, char* from, char* to, char* dest)
{
dest = (char * ) malloc(sizeof(src)+sizeof(from));
int i;
int j;
int check = 1;
for (i = 0; i <= strlen(src) - 1; i++) {
if (src[i] == from[0]) {
for (j = 0; j <= strlen(from) - 1; i++) {
if (src[i+j] != from[j]) {
check = 0;}
else {
continue;
}}}
if (check == 1) {
char * str3 = (char *) malloc(1 + strlen(&src[i]) + strlen(to));
strcpy(str3, &src[i]);
strcat(str3, to);
}
else { continue; }
}
return ;
You allocate memory for a new string in your example, but the calling code cannot acces this variable.
Basically, there are three methods to pass a string. Each has advantages and drawbacks.
Pass a fixed-size buffer
int repl1(char *dest, int n, const char *src, const char *find, const char *repl)
Here, the calling function provides a buffer to which the function can write. It is a good idea to provide a maximum buffer length, so that the function does not overflow that buffer. The arguments, whose contents you don't intend to change should be const, i.e. pointers to unmodifiable data.
Such a function can be void, but it could also return an integer that indicates how long the string in dest is.
The advantage is that you can easily pass automatic buffers. The disadvantage ist that these buffers might be too small for the task.
Call the function like this:
char buf[80];
int n = repl1(buf, sizeof(buf), str, "this", "that");
Return allocated memory
char *repl2(const char *src, const char *find, const char *repl)
Here, the function should allocate new memory to hold the buffer. The function returns the pointer to the new memory. That memory "belongs" to the calling function, which then is responsible for freeing the memory.
The advantage is that the function can allocate enough memory for the task. The disadvantage is that the calling function must take care of managing the new memory.
Call the function like this:
char *dest = repl2(str, "this", "that");
// Do stuff whith 'dest' ...
free(dest);
Pass a pointer to a poiner to char
int repl3(char **dest, const char *src, const char *find, const char *repl)
This is a variant of returning the pointer, where the pointer is passed by reference and can therefore be changed. The function also has access to the old contents to the dest char buffer. That is not useful in your case. I have only mentioned this possibility for completeness.
Call the function like this:
char *buf;
int n = repl3(&buf, str, "this", "that");
This answer addresses the ways of passing data. Your code uses the second method, so you should return dest, but not pass it in as parameter. I have not looked at your function logic.
Void type method won't return anything, what you can do is change the type of your function to string and return a string.
Void means nothing, so you can't return a value with a void function.
I assume you want to use call-by-reference instead of call-by-value, if you want to use a void function.
This means, that you give a pointer to the function, to tell where your array is located. Then you work with your 'real' array, instead of a copy.
[Apart from analyzing the logic of your function] A function with a return type void won't [and can't] return any value using the return statement. Also, worthy to mention, you cannot return more than one value [as you need] using a return statement, either.
To get the return value(s) in your case, you're supposed to call your function and pass pointer(s) to char as argument. Then, inside your function, when you assign/alter values of the locations pointed by those pointers, they will get modified and after returning from your function, in the caller function, you'll have the modified value.
This is another way to have more than one return value at a time from a called function.
printf("%s\n",find_replace("pooppoop poop", "poo", "hel", dest));
char * find_replace(char* src, char* from, char* to, char* dest)
{
dest = (char * ) malloc(sizeof(src)+sizeof(from));
int i;
int j;
int check = 1;
for (i = 0; i <= strlen(src) - 1; i++) {
if (src[i] == from[0]) {
for (j = 0; j <= strlen(from) - 1; i++) {
if (src[i+j] != from[j]) {
check = 0;}
else {
continue;
}}}
if (check == 1) {
char * str3 = (char *) malloc(1 + strlen(&src[i]) + strlen(to));
strcpy(str3, &src[i]);
strcat(str3, to);
return str3 ;
}
else { continue; }
}
return "";
}
The line:
dest = (char * ) malloc(sizeof(src)+sizeof(from));
overrides the address passed in
void find_replace(char* src, char* from, char* to, char* dest)
If you want to allocate memory inside the function (which I think you have to, because the caller cannot know how much to reserve), you have to tell the caller where the result data ends up in. Either you opt for an out-parameter:
void find_replace(char* src, char* from, char* to, char** dest)
{
*dest = malloc(...);
or, what I would prefer, you return the pointer:
char* find_replace(char* src, char* from, char* to)
{
char* dest = malloc(...);
// ...
return dest;
}

Realloc, char**, segfault

There's a function. It is add_lexem and adds an element (char *) in the end of specified array and. If no memory left, it allocates some extra memory (100 * sizeof(char *)). That function causes segfault, which is the problem.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
void add_lexem(char **lexems, int *lexemsc, int *lexem_n, const char *lexem)
{
if (*lexem_n >= *lexemsc) {
lexems = realloc(lexems, sizeof(char *) * (*lexemsc + 100));
*lexemsc += 100;
}
char *for_adding = malloc(sizeof(char) * strlen(lexem));
strcpy(for_adding, lexem);
lexems[*lexem_n] = for_adding;
(*lexem_n)++;
}
int main(void)
{
char **D = malloc(sizeof(char *) * 2);
int lexemsc = 2;
int lexem_n = 0;
add_lexem(D, &lexemsc, &lexem_n, "MEOW");
printf("%s\n", D[0]);
add_lexem(D, &lexemsc, &lexem_n, "BARK");
printf("%s\n", D[1]);
// in this place lexem_n becomes equal lexemsc
add_lexem(D, &lexemsc, &lexem_n, "KWARK");
printf("%s\n", D[2]);
return 0;
}
The output must be
MEOW
BARK
KWARK
but it is
MEOW
BARK
Segmentation fault (core dumped)
You're passing your lexeme parameter by value, when it should be by address:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
// removed unused void ccat(char *str, char c)
void add_lexem(char ***lexems, int *lexemsc, int *lexem_n, const char *lexem)
{
if (*lexem_n >= *lexemsc) {
*lexems = realloc(*lexems, sizeof(char *) * (*lexemsc + 100));
*lexemsc += 100;
}
char *for_adding = malloc(sizeof(char) * strlen(lexem)+1);
strcpy(for_adding, lexem);
(*lexems)[*lexem_n] = for_adding;
(*lexem_n)++;
}
int main(void)
{
char **D = malloc(sizeof(char *) * 2);
int lexemsc = 2;
int lexem_n = 0;
add_lexem(&D, &lexemsc, &lexem_n, "MEOW");
printf("%s\n", D[0]);
add_lexem(&D, &lexemsc, &lexem_n, "BARK");
printf("%s\n", D[1]);
// in this place lexem_n becomes equal lexemsc
add_lexem(&D, &lexemsc, &lexem_n, "KWARK");
printf("%s\n", D[2]);
return 0;
}
Output
MEOW
BARK
KWARK
Note: Triple indirection (i.e. a 3-start-programming) is not something to enter into lightly, though it actually fits what you appear to be trying to do here. Read the above code carefully and make sure you understand how it works.
Edit: added terminator space for added string. (don't know why I missed it, since it was what everyone else seemed to be catching on first-review, duh).
Note: See #wildplasser's answer to this question. Honestly it is the best way to do this, as it tightens the relationship between the string pointer array and the magnitude of said-same. If it is possible to retool your code to use that model, you should do so, and in-so-doing select that answer as the the "correct" solution.
Alternative to avoid the three-star-programming: put everything you need inside a struct:
struct wordbag {
size_t size;
size_t used;
char **bag;
};
void add_lexem(struct wordbag *wb, const char *lexem)
{
if (wb->used >= wb->size) {
wb->bag = realloc(wb->bag, (wb->size+100) * sizeof *wb->bag );
wb->size += 100;
}
wb->bag[wb->used++] = strdup(lexem);
}
The main problem is that you are passing D to the function by value: the assignment
lexems = realloc(...);
has no effect on D. In cases when realloc performs reallocation, D becomes a dangling pointer, so dereferencing it becomes undefined behavior.
You need to pass D by pointer in the same way that you pass lexemsc and &lexem_n, so that the realloc's effect would be visible inside the main function as well.
In addition, your add_lexem does not allocate enough memory for the string being copied: strlen does not count the null terminator, so these two lines
char *for_adding = malloc(sizeof(char) * strlen(lexem));
strcpy(for_adding, lexem);
write '\0' one byte past the allocated space.
The problem may come from :
char *for_adding = malloc(sizeof(char) * strlen(lexem));
strcpy(for_adding, lexem);
try char *for_adding = malloc(sizeof(char) * (strlen(lexem)+1)); to leave some space for the '\0 character.
Edit : and #WhozCraig seems to be right !
Bye,

Use pointer math instead of array indexing

I'm trying to solve a problem found on my C programming book.
#include <stdio.h>
char *f (char s[], char t[], char out[]);
int main(void)
{
char s[] = "ISBN-978-8884981431";
char t[] = "ISBN-978-8863720181";
char out[10];
printf ("%s\n", f(s,t,out));
return 0;
}
char *f (char s[], char t[], char out[]) {
int i;
for (i=0; s[i] == t[i]; i++)
out[i] = s[i];
out[i] = '\0';
return &out[0];
}
As you can see from the code, this code uses as return value &out[0]: does this means that the complete array is used as return value?
char *f (char s[], char t[], char out[]);
int main(void)
{
char s[] = "ISBN-978-8884981431";
char t[] = "ISBN-978-8863720181";
char out[10];
printf ("%s\n", f(s,t,out));
return 0;
}
char *f (char s[], char t[], char out[]) {
for (; *(s+=1) == *(t+=1);)
*(out+=1) = *s;
*(out+1) = '\0';
return out;
}
This is my proposed solution, but while the proposed code returns "ISBN-978-88", mine only returns "8".
The array is smaller than the lenght of the string, how the proposed code can work without any kind of overflow?
Thanks for your responses.
Your code is too aggressive on side effects: the += 1 operation (which is more commonly denoted simply as ++) should be applied after the copy to the output has been made, not after the comparison.
In addition, you need to save the value of the out buffer before incrementing the pointer, so that you could return a pointer to the beginning of the copied string.
char *orig = out;
for ( ; *s == *t ; s++, t++)
*out++ = *s;
*out = '\0';
return orig;
Demo on ideone.
Your code is returning a pointer to the end of the out array. Not the start. You need to stash the initial value of out and return that.
As an aside, the fact that you can do assignments inside a comparison doesn't mean it's a good idea. That code is going to be very hard to maintain.
&out[0] is equivalent to out. Since arrays in C are passed by reference, in a sense, yes it does return the entire array.
Your solution only prints "8" because you're returning a pointer into the middle of the array. When it tries to print the string, it has no way of knowing that it's in the middle of the array/string, thus you only get a substring printed.

Reversing a string in C using pointers?

Language: C
I am trying to program a C function which uses the header char *strrev2(const char *string) as part of interview preparation, the closest (working) solution is below, however I would like an implementation which does not include malloc... Is this possible? As it returns a character meaning if I use malloc, a free would have to be used within another function.
char *strrev2(const char *string){
int l=strlen(string);
char *r=malloc(l+1);
for(int j=0;j<l;j++){
r[j] = string[l-j-1];
}
r[l] = '\0';
return r;
}
[EDIT] I have already written implementations using a buffer and without the char. Thanks tho!
No - you need a malloc.
Other options are:
Modify the string in-place, but since you have a const char * and you aren't allowed to change the function signature, this is not possible here.
Add a parameter so that the user provides a buffer into which the result is written, but again this is not possible without changing the signature (or using globals, which is a really bad idea).
You may do it this way and let the caller responsible for freeing the memory. Or you can allow the caller to pass in an allocated char buffer, thus the allocation and the free are all done by caller:
void strrev2(const char *string, char* output)
{
// place the reversed string onto 'output' here
}
For caller:
char buffer[100];
char *input = "Hello World";
strrev2(input, buffer);
// the reversed string now in buffer
You could use a static char[1024]; (1024 is an example size), store all strings used in this buffer and return the memory address which contains each string. The following code snippet may contain bugs but will probably give you the idea.
#include <stdio.h>
#include <string.h>
char* strrev2(const char* str)
{
static char buffer[1024];
static int last_access; //Points to leftmost available byte;
//Check if buffer has enough place to store the new string
if( strlen(str) <= (1024 - last_access) )
{
char* return_address = &(buffer[last_access]);
int i;
//FixMe - Make me faster
for( i = 0; i < strlen(str) ; ++i )
{
buffer[last_access++] = str[strlen(str) - 1 - i];
}
buffer[last_access] = 0;
++last_access;
return return_address;
}else
{
return 0;
}
}
int main()
{
char* test1 = "This is a test String";
char* test2 = "George!";
puts(strrev2(test1));
puts(strrev2(test2));
return 0 ;
}
reverse string in place
char *reverse (char *str)
{
register char c, *begin, *end;
begin = end = str;
while (*end != '\0') end ++;
while (begin < --end)
{
c = *begin;
*begin++ = *end;
*end = c;
}
return str;
}

Resources