Usuwanie tablicy Mac

0

Witam mam taki problem . Zaczalem uczyc sie programowania w C++(z kursu pana Zelenta) i mam taki problem po lekcji o wskaźnikach spróbowałem sam napisać program do obliczania największej i najmniejszej liczby. Program się kompiluje i działa na Windowsie w CodeBlocks, ale na Macu w Xcode otrzymujębłąd i tablica się nie usuwa.
Błąd:

MinMax(2448,0x1003783c0) malloc: *** error for object 0x1007000ec: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug

Kod źródłowy

#include <iostream>

using namespace std;

int main()
{
    
    int ileLiczb;
    int max,min;
    
    int *tablica;
    tablica = new int [ileLiczb];
    
    int *tablica;
    tablica= new int [ileLiczb];
    
    cout << "Podaj wybrane liczby:\n";
    
    for (int i=0;i<ileLiczb;i++)
    {
        cout <<"Liczba"<<i+1<<":";
        cin >> *tablica;
        tablica++;
        
    }
    
    tablica=tablica-ileLiczb;
    max=*tablica;
    min=*tablica;
    for (int i=0; i<ileLiczb ;i++)
    {
        if ( max<*tablica)
            max=*tablica;
        if ( min>*tablica)
            min=*tablica;
        tablica++;
    }
    cout<<"Max: "<<max<<endl;
    cout<<"Min: "<<min<<endl;
    
    delete [] tablica;
    
    return 0;
    
}
2

Nie możesz mieszać *alloc/free z new/delete. Jak jakiś obiekt tworzysz przy pomocy funkcji z rodziny *alloc to zawsze zwalniasz przy pomocy free, jak tworzysz przy pomocy new to zawsze zwalniasz przy pomocy delete. Nigdy nie mieszasz tych dwóch.

0

Aha dobra wkleiłem wersje już po kombinacjach teraz (edytowałem) jest dokładnie tak jak działa na Windows a na Mac wyświetla ten błąd.

2

Po poprawie towjego kodu by się budował (zduplikowałeś linijki) i uruchomieniu zanim wprowadzam dane wyskakuje błąd.

MacBook-Air-Marek:Downloads $ vi aaa.cpp
MacBook-Air-Marek:Downloads $ g++ -fsanitize=address aaa.cpp 
MacBook-Air-Marek:Downloads $ ./a.out 
Podaj wybrane liczby:
=================================================================
==1111==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000f730 at pc 0x00010fe430c1 bp 0x7fff4fdbdab0 sp 0x7fff4fdbdaa8
READ of size 4 at 0x60200000f730 thread T0
    #0 0x10fe430c0 in main (a.out:x86_64+0x1000010c0)
    #1 0x7fffca53b234 in start (libdyld.dylib:x86_64+0x5234)

0x60200000f731 is located 0 bytes to the right of 1-byte region [0x60200000f730,0x60200000f731)
allocated by thread T0 here:
    #0 0x10fead8eb in wrap__Znam (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x608eb)
    #1 0x10fe42fc5 in main (a.out:x86_64+0x100000fc5)
    #2 0x7fffca53b234 in start (libdyld.dylib:x86_64+0x5234)

SUMMARY: AddressSanitizer: heap-buffer-overflow (a.out:x86_64+0x1000010c0) in main

A opisując to w sposób, który zrozumiesz: używasz zmiennej o nie zdefiniowanej wartości do określenia wielkości danych.
Najpierw wczytaj wartość ileLiczb a dopiero potem jej używaj.

To, że ci zadziałało ci pod Windowsem to jest łut szczęścia (a raczej pech, bo nie widziałeś skutków dużego błedu).

Zresztą, wystarczy traktować ostrzeżenia jak błedy i od razu widać w czym problem:

MacBook-Air-Marek:Downloads $ g++ -Wall -fsanitize=address aaa.cpp 
aaa.cpp:11:23: warning: variable 'ileLiczb' is uninitialized when used here [-Wuninitialized]
    tablica= new int [ileLiczb];
                      ^~~~~~~~
aaa.cpp:7:17: note: initialize the variable 'ileLiczb' to silence this warning
    int ileLiczb;
                ^
                 = 0
1 warning generated.
2

to cin >> *tablica; nie ma sensu
wez jakis lepszy kurs o wskaznikach niz od Zelenta


ogladnij to (cala serie)

0

Zmieniłem ten kod na taki i dalej to samo.

#include <iostream>

using namespace std;

int main()
{
    
    int ileLiczb;
    int max,min;
    
    cout << "Ile liczb chcesz sprawdzic?"<<endl;
    cin >> ileLiczb;
    
    int *tablica;
    tablica = new int [ileLiczb];
    
    cout << "Podaj wybrane liczby:\n";
    
    for (int i=0;i<ileLiczb;i++)
    {
        cout <<"Liczba"<<i+1<<":";
        cin >> tablica[i];
        tablica++;
        
    }
    tablica=tablica-ileLiczb;
 
    max=tablica[0];
    min=tablica[0];
    for (int i=0; i<ileLiczb ;i++)
    {
        if ( max<tablica[i])
            max=tablica[i];
        if ( min>tablica[i])
            min=tablica[i];
        tablica++;
    }
    cout<<"Max: "<<max<<endl;
    cout<<"Min: "<<min<<endl;
    
    delete [] tablica;
    
    return 0;
    
}
2

Nie mieszaj zapisu tablicowego z zapisem wskaźnikowym (zdecyduj się na jeden).
Nie cofasz wskaźnika na początek tablicy przed zwolnieniem pamięci.

3
for (int i=0;i<ileLiczb;i++)
{
    cout <<"Liczba"<<i+1<<":";
    cin >> tablica[i];
    tablica++; 
}

Skoro używasz indeksowania tablica[i] to zwiększanie tablica++ powoduje, że od pewnego momentu zapisujesz do nieswojej pamięci.
Oprócz tego w momencie wywołania delete[] tablica wskaźnik tablica musi wskazywać na początek tej "tablicy" czyli musi mieć pierwotną wartość jaką dostała.

0

Czyli przed funkcją delete muszę dodać
tablica=tablica-x;
gdzie x to o ile wskaźnik został przesunięty?

Jeżeli zrobie coś takiego w takim przykładzie jak poniżej to błędu nie ma :

#include <iostream>

using namespace std;

int ile;

int main()
{
    cout << "Ile liczb w tablicy: ";
    cin>>ile;
   
    int *tablica;
    tablica=new int [ile];
   
    for (int i=0; i<ile; i++)
    {
        cout<<(uintptr_t) tablica<<endl;
        tablica++;
    }
    
    tablica=tablica-ile;
    
    delete [] tablica;
    
    
    return 0;
}
2

Nie rozumiem, po co przesuwasz wskaźnik tablica?
Nie możesz skorzystać z zapisu tablicowego?

for(int i =0; i < ile; ++i)
{
    cin >> tablica[i];
}

lub wskaźnika, bez przesuwania, z odwołaniem do konkretnego elementu?

for(int i =0; i < ile; ++i)
{
    cin >> *(tablica + i);
}

Wtedy nie musisz przejmować się cofaniem wskaźnika, bo go nie ruszasz z miejsca.

C++ ma dynamiczną tablicę: std::vector<>.

0

Podobne przykłady widziałem na różnych kursach z tym przesuwaniem tablicy. I było też wspomniane ,że im więcej wskaźników tym lepiej. Jak cofam ten wskaźnik to się kompiluje i nie wyrzuca błędów. To jak to w końcu powinno być?

0
Sebastian Pacuk napisał(a):

Podobne przykłady widziałem na różnych kursach z tym przesuwaniem tablicy. I było też wspomniane ,że im więcej wskaźników tym lepiej.

Polecam zmienić kursy. Wskaźniki są trudne do zrozumienia i poprawnego użycia dla początkujących, a nawet jak już je zrozumiesz to chcesz ich unikać jak się da.

Jak cofam ten wskaźnik to się kompiluje i nie wyrzuca błędów. To jak to w końcu powinno być?

Jak się uczysz o wskaźnikach to możesz tak zrobić, ale potem używaj zapisu tablicowego.

0

Może mógłbyś /moglibyście coś polecić?

1 użytkowników online, w tym zalogowanych: 0, gości: 1