Malloc kullanımı

Başlatan mr.engineer, 04 Şubat 2021, 00:11:24

mr.engineer

Merhaba aşağıdaki kod satırı Windows'da DEV C++ ve Linux'da çalıştırınca doğru çalışıyor, fakat Visual Studio'da hata veriyor.

char **ptr;

ptr = (char **)malloc(sizeof(char *));


Visual studio'da eğer şu şekilde yazarsam doğru çalışıyor

ptr = (char **)malloc(sizeof(char *)*2);  (Çarpı 2 sorunu çözüyor.)


Çok saçma geldi bana. Windowsta DevC++ gcc kullanıyor. Linux'da gcc ile çalıştırdım. Visual studio derleyicisi niye böyle bir sorun çıkarıyor? 

Çarpı 2 nin anlamı nedir?

brandice5

Kodun tamamını görmeden birşey söylemek zor. Hatada ne yazıyor?

32/64 bit sorunu olabilir. sizeof(char*) 32 bitte 4 byte, 64 bitte 8byte döndürür (32*2=64).

mr.engineer

#2
Alıntı yapılan: brandice5 - 04 Şubat 2021, 01:09:00Kodun tamamını görmeden birşey söylemek zor. Hatada ne yazıyor?

32/64 bit sorunu olabilir. sizeof(char*) 32 bitte 4 byte, 64 bitte 8byte döndürür (32*2=64).


Hocam sorunu anlamadım ama bugün denedim çözüldü visual studio'da çalışıyor fakat bu sefer de Linux 'da çalıştıramadım. Aşağıda paylaşıyorum.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char **split(char *, const char *);

int main(void)
{
    char names[] = "ali, veli, selami ,ali";
    char **str;
    int i;

    if ((str = split(names, ", ")) == NULL)
    {
        fprintf(stderr, "cannot split!..\n");
        exit(EXIT_FAILURE);
    }

    for (i = 0; str[i] != NULL; ++i)
        printf("%s\n", str[i]);

    free(str);

    return 0;
}
 


char **split(char *str, const char *delim)
{
    char **ptr, **temp;
    char *p;
    int i = 1;
    size_t k = 2;
    k = sizeof(char *);

    p = strtok(str, delim);

    if (p == NULL)
    {
        fprintf(stderr, "empty string!..");
        return NULL;
    }

    ptr = (char **)malloc(sizeof(char *));

    if (ptr == NULL)
    {
        fprintf(stderr, "allocation is failed!..");
        return NULL;
    }

    *ptr = p;
    temp = ptr;
    while (p != NULL)
    {
        p = strtok(NULL, delim);
        if (p != NULL)
        {

            ptr = (char **)realloc(ptr, k+=4);
            //k++;
            if (ptr != NULL)
            {
                *(temp + i) = p;
                i++;
            }
            else
            {
                fprintf(stderr, "allocation is failed!..");
                free(ptr);
                return NULL;
            }
        }
    }
    ptr = (char **)realloc(ptr, (size_t)(sizeof(char *) * k));

    ptr[i] = NULL;
    return ptr;
}

Linux'da çalışmayan kısım burası
ptr = (char **)realloc(ptr, k+=4);

Eğer bunu şu şekilde değiştirirsek çalışıyor. (k başlangıçta k=2 olarak tanımlandı)

            temp = (char **)realloc(temp, sizeof(char*)*k);
            k++;


brandice5

k+=4 dersen her zaman (32 bitte de, 64 bitte de) char pointer için 4 byte bellek ayırmış olursun. Bu kullanım yanlış. 64 bitte char pointer için 4 byte ayırırsan bütün bellek yerleşimi bozulur. sizeof(char*)*k doğru olan.

Kod biraz ezbere yazılmış gibi, kodu baştan sona gözden geçirip tekrar yazmanı tavsiye ederim.

Örneğin;
size_t k = 2;
k = sizeof(char *);

buraya dikkat edilmemiş.

mr.engineer

Alıntı yapılan: brandice5 - 04 Şubat 2021, 15:14:13Örneğin;
size_t k = 2;
k = sizeof(char *);

buraya dikkat edilmemiş.

Hocam burda char pointerın boyutuna bakmak için yazdım. k burdan 4 geliyor, bu yüzden de

ptr = (char **)realloc(ptr, k+=4); şeklinde yazdım.

Şimdi fark ettim Visual studio x86 da yani 32 bitte çalışıyormuş o yüzden sorun çıkarmıyor. Aynı kodu Linux'a geçirince ordaki derleme 64 bit olduğundan çalışmıyor.

Bu arada kodda nereyi beğenmediniz :D
32/64 bit kaynaklı olacağını ihmal etmişim.

Teşekkürler

volkanunal

Anladığım kadarıyla parse etmeye çalışıyorsunuz elinizde bulunan string literallerini hocam. İş yerindeyim şöyle bir şey çıkardım ama test fonksiyonlarının yazılması lazım.

 1. Mümkün olduğunca const doğruluğunu sağlamaya çalışmak gerekiyor kodlarda.
 2. Eğer embedded taraf için ise kod, strtok çok uygun bir fonksiyon değil(manipülasyona gerçekten açık)


/******************************************************************************

                            Online C Compiler.
                Code, Compile, Run and Debug C program online.
Write your code in this editor and press "Run" button to compile and execute it.

*******************************************************************************/

#include <stdio.h>
#include <string.h>

#define MAX_SIZE 15
int main()
{
    const char* name[] = {"veli", "volkan", "ahmet", "mehmet", "selam" };
    
    char splitted[ sizeof(name) / sizeof(name[0])][MAX_SIZE] = { 0 };
    
    const char **p = &name[0];
    
    static int idx = 0;
    
    for (int i = 0; i < sizeof(name)/ sizeof(name[0]); ++i)
    {
        if (*p != NULL)
        {
            memcpy(splitted[idx], *p, strlen(*p));
            ++p;
            idx++;
        }
    }
    
    idx = 0;
    
    char test_buf[MAX_SIZE] = { 0 };
    
    for (int i = 0; i < 5; ++i)
    {
        memcpy(test_buf, splitted[i], MAX_SIZE);
        printf("\r\n %s", test_buf);
    }
    
    return 0;
}
Primum nil nocere

brandice5

#6
@volkanunal eline sağlık. Aslında @mr.engineer in kodu ile senin kodun tam olarak aynı değil. Senin kodunda stringler zaten NULL ile sonlandırıldığından aslında bir split işlemi yok, sadece kopyalama var. Kodunla ilgili birkaç nokta;

1. memcpy(splitted[idx], *p, strlen(*p)); kopyalama kısmında MAX_SIZE kontrolü yok. name dizisindeki stringlere MAX_SIZE'dan fazla girersen kopyalarken splitted dizisinde overlap oluşuyor.

2. static int idx = 0; kısımndaki "static" keyword'un bir işlevi yok. Varsa yazabilirsin.

3. Sondaki yazdırma işlemi üçüncü bir dizi olmadan printf("\r\n %s", splitted[ i ] ); ile de yazdırılıabilir.


volkanunal

#7
Alıntı yapılan: brandice5 - 04 Şubat 2021, 16:55:16@volkanunal eline sağlık. Aslında @mr.engineer in kodu ile senin kodun tam olarak aynı değil. Senin kodunda stringler zaten NULL ile sonlandırıldığından aslında bir split işlemi yok, sadece kopyalama var. Kodunla ilgili birkaç nokta;

1. memcpy(splitted[idx], *p, strlen(*p)); kopyalama kısmında MAX_SIZE kontrolü yok. name dizisindeki stringlere MAX_SIZE'dan fazla girersen kopyalarken splitted dizisinde overlap oluşuyor.

2. static int idx = 0; kısımndaki "static" keyword'un bir işlevi yok. Varsa yazabilirsin.

3. Sondaki yazdırma işlemi üçüncü bir dizi olmadan printf("\r\n %s", splitted[ i ] ); ile de yazdırılıabilir.



o static'i for içerisinde yazdığım için kalmış hocam çıkarınca silmemişim. bu arada evet ben arkadaşın kodunu dikkatli incelemedim. Onun yapı benimkinden farklıymış. Ben parse fonksiyonuna baktım sadece :) Evet 3.bir diziye gerek yok tabi .
Primum nil nocere

mr.engineer

Alıntı yapılan: volkanunal - 04 Şubat 2021, 16:03:12Anladığım kadarıyla parse etmeye çalışıyorsunuz elinizde bulunan string literallerini hocam. İş yerindeyim şöyle bir şey çıkardım ama test fonksiyonlarının yazılması lazım.

 1. Mümkün olduğunca const doğruluğunu sağlamaya çalışmak gerekiyor kodlarda.
 2. Eğer embedded taraf için ise kod, strtok çok uygun bir fonksiyon değil(manipülasyona gerçekten açık)

 Senin verdiğin örnek farklı, birden fazla string var, strtok'a gerek yok zaten burda. Benim verdiğim split işlemi için strtok kullanılabilir. Güzel bir fonksiyon sadece dikkatli olmak lazım aynı anda tek bir string ile kullanılabiliyor.