Exception thrown at 0x00007FF83DE5499E (ucrtbased.dll) in HW5_NEW.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF. Error in my code. What could cause it?

Ron Petlyarsky 1 Reputation point
2023-01-02T10:17:35.543+00:00

Hello everyone! I am new to coding in C++ and I'm studying 2d dynamic arrays and I am having a problem with handling pointers and dynamic allocations. The program crushes in the third func loop and gives me the error in the title. I know it's related to memory mismanagement but I honestly don't know how to approach it at this point :( Would appreciate if you could point me to the problematic section in my code and explain it. Thank you!

#include <iostream>  
#include <time.h>  
#include <string.h>  
using namespace std;  
const int lowLevel = 1, highLevel = 3, noNames = 0, nullCell = 1, maxLen = 31, maxIncrease = 2;  
const char enter = '\n';  
  
void insertDynamicName(char* p, char* name, int currentLen)  
{  
    char *pTemp = new char[currentLen];  
    if (pTemp != nullptr)  
    {  
        strcpy_s(pTemp, currentLen, name);  
        p = pTemp;  
    }  
      
}  
  
void pCharArrDelete(char** pArr, int rows)  
{  
    for (int i = 0; i < rows; i++)  
    {  
        delete[]pArr[i];  
    }  
    delete[]pArr;  
}  
  
void copyCharPointers(char** source, char** dest, int qty)  
{  
    for (int i = 0; i < qty; i++)  
        dest[i] = source[i];  
}  
  
void addNullPtrs(char** studentNames, int maxSize, int i)  
{  
    while (i < maxSize)  
    {  
        studentNames[++i] = nullptr;  
    }  
}  
  
char** addNames(int* pMaxSize, int* pNumNames)  
{  
    char inputName[maxLen] = { 0 };  
    int currentLen = 0, i;  
    char** studentNames = new char* [*pMaxSize], ** temp = nullptr;  
    if (studentNames == nullptr)  
    {  
        return nullptr;  
    }  
    for (i = 0; *inputName != enter; i++)  
    {  
        cout << "\nPlease enter the name of the student: ";  
        cin >> inputName;  
        currentLen = strlen(inputName) + nullCell;  
        insertDynamicName(studentNames[i], inputName, currentLen);  
        if (studentNames[i] == nullptr)  
        {  
            pCharArrDelete(studentNames, *pNumNames);  
            return nullptr;  
        }  
        if (i == *pMaxSize)  
        {  
            temp = new char* [*pMaxSize];  
            copyCharPointers(studentNames, temp, *pMaxSize);  
            pCharArrDelete(studentNames, *pMaxSize);  
            studentNames = nullptr;  
            *pMaxSize *= maxIncrease;  
            studentNames = new char* [*pMaxSize];  
            if (studentNames == nullptr)  
            {  
                return nullptr;  
            }  
            copyCharPointers(temp, studentNames, i);  
            addNullPtrs(studentNames, *pMaxSize, i);  
            pCharArrDelete(temp, i);  
            temp = nullptr;  
        }  
    }  
    *pNumNames = ++i;  
    return studentNames;  
}  
  
int main()  
{  
    srand(time(NULL));  
    int numNames = 0, maxSize = 1;  
    int* pMaxSize = &maxSize, * pNumNames = &numNames;  
    char** studentNames = addNames(pMaxSize, pNumNames);  
    if (**studentNames == enter)  
    {  
        cout << "No student names were entered. Please try again.";  
        numNames = 0;  
        pCharArrDelete(studentNames, maxSize);  
        studentNames = addNames(pMaxSize, pNumNames); //user will be prompted to try entering the names again, since he didn't enter anything and tried to continue the input  
    }  
    if (studentNames == nullptr) //allocation failed  
    {  
        cout << "Error in memory allocation! Program will exit.\n";  
        return 0;  
    }  
    for (int i = 0; i < numNames; i++)  
        cout << studentNames[i] << endl;  
  
    return 0;  
  
}  
Developer technologies | C++
{count} votes

2 answers

Sort by: Most helpful
  1. Minxin Yu 13,506 Reputation points Microsoft External Staff
    2023-01-03T07:41:03.65+00:00

    Hi, @Ron Petlyarsky

    Add & in insertDynamicName();

    void insertDynamicName(char* &p, char name[], int currentLen)  
    

    In addition, copyCharPointers copies the pointer. But the pointers will be deleted in pCharArrDelete. You need to store the value.

    Best regards,

    Minxin Yu


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

  2. WayneAKing 4,931 Reputation points
    2023-01-05T07:29:37.18+00:00

    While not related to any of the current issues you have with
    your program's operation, there is a basic (and somewhat
    common) error in the way you are testing for failure
    of the new operator. C++ compilers from many years ago
    would generate code that would return NULL if a new
    or new[] failed (usually because of insufficient heap
    memory available to satisfy the request).

    However, for many years now that is not what happens.
    Instead, a bad_alloc exception will be thrown if
    new/new[] fails. So testing for nullptr after each
    new/new[] is pointless as the code will never be
    executed (and the pointer will not be set to nullptr
    or NULL/null/0).

    To have new/new[] return a nullptr instead of throwing
    an exception you must use the nothrow version:

    new(std::nothrow) ...

    So if you want your code to actually work as written
    in the event of an allocation failure you must change
    all of your new statements to use that form.

    "If there's insufficient memory for the allocation request,
    operator new throws a std::bad_alloc exception. Or, it returns
    nullptr if you've used the placement form new(std::nothrow),
    or if you've linked in non-throwing operator new support.
    For more information, see Allocation failure behavior."

    new and delete operators
    https://learn.microsoft.com/en-us/cpp/cpp/new-and-delete-operators?view=msvc-170

    Also see:

    new operator (C++)
    https://learn.microsoft.com/en-us/cpp/cpp/new-operator-cpp?view=msvc-170

    By way of an example which illustrates both behaviours,
    you can build this small program and run it with a
    breakpoint set on the return statement. Try it first with
    the statement:

    cpp = new char*;

    Check the output in the console window.

    Then rebuild it using the nothrow version:

    cpp = new (nothrow) char*;

    Check the output in the console window.

    #include <iostream>  
    using namespace std;  
      
    int main()  
    {  
        int n;  
        char ** cpp = nullptr;  
        for (n = 0; n < 2000000000; ++n)  
        {  
            try{  
                cpp = new char*; // throws a bad_alloc exception  
                //cpp = new (nothrow) char*; // returns nullptr  
            }  
            catch (std::bad_alloc)  
            {  
                cout << "new failed! (bad_alloc)" << endl;  
                break;  
            }  
              
            if (cpp == nullptr)  
            {  
                cout << "new failed! (nullptr)" << endl;  
                break;  
            }  
        }  
      
        return 0;  
    }  
      
    
    • Wayne
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.