I have the following program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 255
char * decrypt(char *p, int key){
char *tmp;
for(int i = 0; p[i] != '\0'; i++){
tmp[i] = p[i]-key;
}
return tmp;
}
int main(void){
printf("Hallo Welt!");
printf("%s\n", decrypt("ibmmp", 1));
return EXIT_SUCCESS;
}
When I compile it with gcc -Wall i get the Warning tmp could get uninitialized in this function [-Wmaybe-uninitialized] tmp[i] = p[i]-key(translated from german) and segmentation fault (core dumped) ./crypto when i run it
What is causing that error?
I know this quesion has been asked many times, but i could not fix this warning, because other people had different sourcecodes and i couldn't adapt it to my problem.
You need to allocate 'tmp' and then, keeping with good 'c' coding, check that the allocation was successful. I assume you have MAX defined so you can set an upper-bound on the length of your string, so I use that below. If MAX is intended to be the number of characters without a null, then you need to 'malloc(MAX +1)'. If it is intended to include NULL, then just leave the code as defined below. You also want to decide what to return on failure of the malloc. I return NULL, but you may want to do something different depending on your needs.
Also be aware, that this function is returning allocated memory, so someone needs to free it so you aren't leaking memory.
char * decrypt(char *p, int key){
char *tmp;
tmp = (char *) malloc(MAX);
if(!tmp)
return NULL;
for(int i = 0; p[i] != '\0'; i++){
tmp[i] = p[i]-key;
}
return tmp;
}
Allocate memory for tmp before using it. Make sure you null-terminate the string before returning it.
// Make the input a const string.
// char * decrypt(char *p, int key){
char * decrypt(char const* p, int key){
char *tmp = malloc(strlen(p) + 1); // Allocate memory
int i = 0;
for( ; p[i] != '\0'; i++){
tmp[i] = p[i]-key;
}
tmp[i] = '\0'; // null terminate.
return tmp;
}
Make sure you deallocate the memory. Just using
printf("%s\n", decrypt("ibmmp", 1));
will result in a memory leak.
int main(void){
printf("Hallo Welt!");
char* dec = decrypt("ibmmp", 1)
printf("%s\n", dec);
free(dec); // Deallocate memory.
return EXIT_SUCCESS;
}
Related
Jus started learning about pointers and im stuck with this program outputting a segmentation fault.
Its supposed to copy the first 10 Characters of a string to the location pointed by the double pointer
using gdb ive found that **pt=*s; produces the seg fault
#include <stdio.h>
#include <stdlib.h>
void str1(char *s, char **pt);
void str1(char *s, char **pt){
for(int i=0;i<10;i++){
**pt=*s;
pt++;
s++;
}
}
int main (void) {
char str[30] = "223This is test";
char *ptr;
str1(str, &ptr);
printf("%s", ptr);
return 0;
}
First of all ptr is not initialized, you can't really use it until you reserve space for it or store a valid memory address in it, i.e. make it point to some valid variable.
char *ptr = malloc(11);
Then you need to increment it properly in the function:
(*pt)++;
Once the copy is completed you need to null terminate the char array so it can be treatead as a string, aka a null terminated char array.
**pt = '\0';
Now as ptr was passed as a pointer to pointer, the increment is known by the caller, main in this case, so when you try to print it, it prints nothing because it's pointing to the end of the char array, we need to bring it back to the beggining.
*pt -= 10;
Corrected code with comments taking yours as base:
Live demo
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
void str1(char *s, char **pt) {
for (int i = 0; i < SIZE; i++) {
**pt = *s;
(*pt)++; //properly increment pt
s++;
}
**pt = '\0'; //null terminate copied string
//since ptr was passed as **, the increment is known by the caller
//now ptr will be pointing to the end of the string
//we have to bring it back to the beginning
*pt -= SIZE;
}
int main(void) {
char str[] = "223This is test";
char *ptr = malloc(SIZE + 1); //space for 10 character + null-terminator
//check for allocation errors
if(ptr == NULL){
perror("malloc");
return EXIT_FAILURE;
}
str1(str, &ptr);
printf("%s", ptr);
free(ptr);
return EXIT_SUCCESS;
}
You probably want this:
#include <stdio.h>
#include <stdlib.h>
void str1(char* s, char** pt) {
char *p = malloc(100); // allocate memory for destination
*pt = p; // store it for the caller
for (int i = 0; i < 10; i++) {
*p = *s;
p++;
s++;
}
*p = 0; // put string terminator, otherwise printf won't work correctly
}
int main(void) {
char str[30] = "223This is test";
char *ptr; // for now p points nowhere
str1(str, &ptr); // now p points to the memory allocated in str1
printf("%s", ptr);
free(ptr); // free memory for completeness
return 0;
}
i was playing arround with the C malloc and free tools and i had a weird memory leak. Does someone has an idea about it?
The goal is to successfully free a char**.
So in the function freezer, i free every char* in the char** and the i free the char**.
But Valgrind (my leaks detector on linux) find 20 bytes in 4 blocks leaked (i don't know if i can write 'leaked' XD)
The more interesting part is that if i do a bigger char** by adding a char* in it, it leak 5 more bytes of memory in another block :/.
#include <stdio.h>
#include <stdlib.h>
void freezer(char ***array, int length){
int i;
i = -1;
while (*array[++i] != NULL){
free(*array[i]);
}
free(*array);
}
int main(){
char **big;
int len = 4;
int i;
big = malloc(sizeof(char *) * (len + 1));
i = -1;
while (++i < len){
big[i] = malloc(sizeof(char) * 5);
big[i][0] = 't';
big[i][1] = 'e';
big[i][2] = 's';
big[i][3] = 't';
big[i][4] = '\0';
}
big[i] = NULL;
i = -1;
while (++i < len){
printf("i: %d\t%s\n", i, big[i]);
}
freezer(&big, len);
return (0);
}
You can directly copy/past/run the code as it is.
So if you have any clue about the error/C problem, please let me know.
big[i] = NULL; causes a buffer overflow. You only allocated space for a total of len entries, plus one byte; but at that point i == len.
Perhaps you meant big = malloc(sizeof(char *) * (len + 1));
Also, the freezer function dereferences and frees the wrong thing. Either change it to accept char **array , or replace all occurrences of array with (*array) inside the function. The former is preferable, there is no need to pass by reference in order to call free.
Your loop structure is weird for no apparent reason; it's normal to use:
for (i = 0; i < len; ++i)
which is the same logic but will make your code easier to digest for people reading it.
Also, don't cast malloc
I am playing around a bit in C and trying to write a test program for kind of oop in c programming. I get the Error of the headline in Visual Studio 2010. In using gcc i don't get this error.
Can anyone point me to what i am doing wrong, besides using the wrong language for oop, and other off topic suggestions.
It seems like the error occurs when i free the top object in string_dispose, but i am not shure if that really says a lot about the location of the error.
Also any suggestions regarding code improvements are welcome. Using array syntax is not an option, because i want to try out pointer arithmetic.
The header file "strings.h":
#ifndef STRINGS_H
#define STRINGS_H
struct strings
{
char* s;
int len;
};
typedef struct strings string;
void string_init(string* s, char* chars, int len);
string* string_new(char* chars, int len);
void string_dispose(string* s);
#endif
The source file "strings.c":
#include "strings.h"
#include <stdlib.h>
void string_init(string* self, char* chars, int len)
{
int i;
self->s = (char*)malloc((len + 1) * sizeof(char*));
for (i = 0; i < len; i++)
{
*(self->s + i) = *(chars + i);
}
*(self->s + len) = '\0';
self->len = len;
}
string* string_new(char* chars, int len)
{
string* self;
self = (string*)malloc(sizeof(string*));
string_init(self, chars, len);
return self;
}
void string_dispose(string* self)
{
free(self->s);
free(self);
}
The main file:
#include <stdlib.h>
#include <stdio.h>
#include "strings.h"
int main(int argc, char* argv)
{
string* s;
int n = 5;
char* x = (char*)malloc((n + 1) * sizeof(char*));
x[0] = 'f';
x[1] = 'u';
x[2] = 'b';
x[3] = 'a';
x[4] = 'r';
x[5] = '\0';
s = string_new(x, n);
printf("the string: %s\n", s->s);
printf("the length: %d\n", s->len);
string_dispose(s);
printf("This is way more important");
return 0;
}
When you try to allocate memory for string, you only allocate enough memory for a pointer (string*):
self = (string*)malloc(sizeof(string*));
You should allocate sizeof(string) instead, since you want enough space to store the whole struct, not just a pointer to one. Since sizeof(string*) is smaller than sizeof(string), the other code writes outside of the allocated area, causing heap corruption.
Similarly, when mallocing memory for the characters, the size should be (len + 1) * sizeof(char).
Here are the codes of a program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * cloning(char * q){
char s[strlen(q)];
int i;
for(i = 0; i < strlen(q); i++)
s[i] = q[i];
return s;
}
int main(){
char q[] = "hello";
char *s = cloning(q);
return 0;
}
After the compilation a warning appears, so I changed the returned value like this:
char *b = s;
return b;
In this way the warning can be solved. However I found that inside the function cloning(), sizeof(s) is 5, but strlen(s) is 7. And if I change char s[strlen(q)] simply to char s[5], the output is still incorrect. Can anybody explain this problem to me? Thank you very much.
char s[strlen(q)] is a local variable, and hence when you return its address, it results in undefined behaviour. Thus either you could use strdup() or malloc() to dynamically allocate the array, thus ensuring that the array s is available on the heap when you return from the function. The returned array would need to be free()-ed as well, else it would have a memory leak :)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * cloning(char * q){
char *s = malloc(strlen(q)+1);
// if you write char s[strlen(q)], it is defined locally, and thus on return gives an undefined behaviour
int i;
for(i = 0; i < strlen(q)+1; i++)
s[i] = q[i];
return s;
}
int main(){
char q[] = "hello";
char *s = cloning(q);
free(s);
return 0;
}
char s[strlen(q)];
is a variable-length array. Like a malloc'ed buffer its size is determined at runtime. Unlike a malloc'ed buffer, it ceases to exist when the function returns.
multiple issues with this code:
char * cloning(char * q){
char s[strlen(q)]; // s has strlen size but needs strlen + 1 to hold \0
int i;
for(i = 0; i < strlen(q); i++) // should copy the \0 otherwise q is not a valid string
s[i] = q[i];
return s;// returns the address of a local var == undef. behavior
}
if you want to clone a string just do strdup()
char* cloning(char* q)
{
return strdup(q);
}
or the equivalent
char * cloning(char * q)
{
char* s = malloc(strlen(q)+1);
int i;
for(i = 0; i < strlen(q)+1; i++)
s[i] = q[i];
return s;
}
The proper way to do this with standard C, no matter version of the C standard, is this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* cloning (const char* str)
{
char* clone;
size_t size = strlen(str) + 1;
clone = malloc(size);
if(clone == NULL)
{
return NULL;
}
memcpy(clone, str, size);
return clone;
}
int main(){
char original[] = "hello";
char* clone = cloning(original);
if(clone == NULL)
{
puts("Heap allocation failed.");
return 0;
}
puts(clone);
free(clone);
return 0;
}
Dynamic arrays in C are declared using Malloc and Calloc. Try googling it.
Eg:
char *test;
test = (char *)malloc(sizeof(char)*Multiply_By);
In C,static array is in stack,after function return,it's been destoryed. and string with char has a '\0' end. But strlen don't include it. For example.char q[] = "hello"; strlen(q) = 5,but the real size is 6
If you want to copy a string, the last '\0' must be added at the end.or using
char *s = malloc(sizeof(q)); ...; for(i = 0; i < sizeof(q); i++)
s[i] = q[i];
you also need to free it after using.Maybe become a mem leak.
Hope this can help u.
I have declared the following struct:
typedef struct _RECOGNITIONRESULT {
int begin_time_ms, end_time_ms;
char* word;
} RECOGNITIONRESULT;
There is a method that creates an array of RECOGNITIONRESULT and fills it (for test purposes only):
void test_realloc(RECOGNITIONRESULT** p, int count){
int i;
*p = (RECOGNITIONRESULT *)realloc(*p, count * sizeof(RECOGNITIONRESULT));
for (i = 0; i < count; i++){
(*p)[i].begin_time_ms = 2*i;
(*p)[i].end_time_ms = 2*i+1;
(*p)[i].word=(char *) malloc ( (strlen("hello"+1) * sizeof(char ) ));
strcpy((*p)[i].word,"hello");
}
}
The method to free memory is:
void free_realloc(RECOGNITIONRESULT* p, int count){
int i = 0;
if(p != NULL){
if (count > 0){
for (i = 0; i < count; i++){
free(p[i].word); //THE PROBLEM IS HERE.
}
}
free(p);
}
}
The main method calls those methods like this:
int main(int argc, char** argv)
{
int count = 10;
RECOGNITIONRESULT *p = NULL;
test_realloc(&p,count);
free_realloc(p,count);
return 0;
}
Then if I try to free the memory allocated for "word", I get the following error:
HEAP CORRUPTION DETECTED: after normal block (#63) at 0x003D31D8.
CRT detected that the application wrote to memory after end of heap buffer.
Using the debugger I've discovered that the crash occurs when calling free(p[i].word);
What am I doing wrong? How can I free he memory for the strings?
The problem is in your allocation of memory for word. strlen("hello"+1) should be strlen("hello")+1.
Since you appear to allocate a whole array of structures in one strike
RECOGNITIONRESULT **p;
*p = (RECOGNITIONRESULT *)realloc(*p, count * sizeof(RECOGNITIONRESULT));
you can free them in one call to free() as well :
void free_realloc(RECOGNITIONRESULT *p, int count){
free(p);
}
And the strlen("hello"+1) is also wrong, as detected by Chowlett.