A closer look at CreateArr & DestroyArr, with help from ChatGPT

Started by Ad_Rienks, July 08, 2024, 03:39:33 PM

Previous topic - Next topic

MrBcx

Quote from: Ad_Rienks on July 08, 2024, 10:46:26 PM

Thanks; it is built, gives a few warnings, but executes without errors.

How did you unhide and delete the garbage?

I am seriouly thinking about using alternatives; even compiling from the command line is easier.

Lots of ways to unhide folders/files ... easiest to explain is Windows File Explorer | View | Show | Hidden Items

Ad_Rienks

Quote from: MrBcx on July 08, 2024, 10:23:21 PM
Quote from: Ad_Rienks on July 08, 2024, 09:34:19 PM
Quote from: MrBcx on July 08, 2024, 09:10:30 PM
Quote from: Ad_Rienks on July 08, 2024, 08:14:28 PM
Isn't it strange? The same code; Using Bed, I build with MS VC++ (UCRT), result no warning and runs without errors.

The same code: Using Visual Studio, giving an error! Very strange!?

Patient:  Doctor, it hurts when I do this!

Doctor:  Don't do that!

So, your advice is: "Do not use Visual Studio"?

Ad,

I was making a joke ...

Attached to this post is my MSVC project.  It works for me, it should work for you.

I had to unhide and delete about 130 MB of garbage from the project folder
that Visual Studio produced
for an executable that is only 67kb.

Yeah ... I'm not a fan of Visual Studio.

Thanks; it is built, gives a few warnings, but executes without errors.

How did you unhide and delete the garbage?

I am seriouly thinking about using alternatives; even compiling from the command line is easier.

MrBcx

Quote from: Ad_Rienks on July 08, 2024, 09:34:19 PM
Quote from: MrBcx on July 08, 2024, 09:10:30 PM
Quote from: Ad_Rienks on July 08, 2024, 08:14:28 PM
Isn't it strange? The same code; Using Bed, I build with MS VC++ (UCRT), result no warning and runs without errors.

The same code: Using Visual Studio, giving an error! Very strange!?

Patient:  Doctor, it hurts when I do this!

Doctor:  Don't do that!

So, your advice is: "Do not use Visual Studio"?

Ad,

I was making a joke ...

Attached to this post is my MSVC project.  It works for me, it should work for you.

I had to unhide and delete about 130 MB of garbage from the project folder
that Visual Studio produced
for an executable that is only 67kb.

Yeah ... I'm not a fan of Visual Studio.




Ad_Rienks

Quote from: MrBcx on July 08, 2024, 09:10:30 PM
Quote from: Ad_Rienks on July 08, 2024, 08:14:28 PM
Isn't it strange? The same code; Using Bed, I build with MS VC++ (UCRT), result no warning and runs without errors.

The same code: Using Visual Studio, giving an error! Very strange!?

Patient:  Doctor, it hurts when I do this!

Doctor:  Don't do that!

So, your advice is: "Do not use Visual Studio"?

MrBcx

Quote from: Ad_Rienks on July 08, 2024, 08:14:28 PM
Isn't it strange? The same code; Using Bed, I build with MS VC++ (UCRT), result no warning and runs without errors.

The same code: Using Visual Studio, giving an error! Very strange!?

Patient:  Doctor, it hurts when I do this!

Doctor:  Don't do that!

Ad_Rienks

Isn't it strange? The same code; Using Bed, I build with MS VC++ (UCRT), result no warning and runs without errors.

The same code: Using Visual Studio, giving an error! Very strange!?

Ad_Rienks

I detected one difference; I should call my source .cpp, not .c. Now it builds without errors, warnings, messages.

But running the prog, after cleaning and rebuilding, running "Start Without Debugging CTRL-F5" an error is emitted, see attachment.

MrBcx

Ad,

I generally do not use Visual Studio but for the sake of argument, I created a console project,
VS generated some "Hello, World" c++ code, I overwrote that with the code that BCX emitted
from S151.  I built the project:

Build started at 5:19 PM...
1>------ Build started: Project: ConsoleApplication1, Configuration: Debug x64 ------
1>ConsoleApplication1.cpp
1>ConsoleApplication1.vcxproj -> C:\temp\vc\s151\ConsoleApplication1\x64\Debug\ConsoleApplication1.exe
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
========== Build completed at 5:19 PM and took 02.891 seconds ==========

I ran the executable -- it ran perfectly.

On the subject of warnings, take a look inside Bc.bas ... search for SUB Emit_CompilerDefines
and you'll see a selection of warnings being conditionally disabled.  The warnings can be enabled in
BCX using $WARNINGS_ON.  There are many viewpoints on warnings and I certainly have mine.




Ad_Rienks

More problems; running the app in VS gives an error message; see attachment!

Ad_Rienks

You should not get me wrong; I never thought that the ChatGPT solution was the best, better than the BCX code!

I started my conversation with ChatGPT, because of warnings in Visual Studio editor. I have copied the BCX S151 generated code in the VS editor, and upon building 9 warnings are emitted.

Quote
Severity   Code   Description   Project   File   Line   Suppression State   Details
Warning   C6308   'realloc' might return null pointer: assigning null pointer to 'dynavar', which is passed as an argument to 'realloc', will cause the original memory block to be leaked.   dyn_arr_test   D:\projecten\C Programming\dyn_arr_test\dyn_arr_test.c   153      
Warning   C6011   Dereferencing NULL pointer 'vp'.    dyn_arr_test   D:\projecten\C Programming\dyn_arr_test\dyn_arr_test.c   194      
Warning   C6385   Reading invalid data from 'vp'.   dyn_arr_test   D:\projecten\C Programming\dyn_arr_test\dyn_arr_test.c   194      
Warning   C6386   Buffer overrun while writing to 'vp'.   dyn_arr_test   D:\projecten\C Programming\dyn_arr_test\dyn_arr_test.c   194      
Warning   C6386   Buffer overrun while writing to 'b'.   dyn_arr_test   D:\projecten\C Programming\dyn_arr_test\dyn_arr_test.c   256      
Warning   C6387   'b' could be '0':  this does not adhere to the specification for the function 'strcpy'.    dyn_arr_test   D:\projecten\C Programming\dyn_arr_test\dyn_arr_test.c   256      
Warning   C6387   'b' could be '0':  this does not adhere to the specification for the function 'strcat'.    dyn_arr_test   D:\projecten\C Programming\dyn_arr_test\dyn_arr_test.c   260      
Warning   C6308   'realloc' might return null pointer: assigning null pointer to 'b', which is passed as an argument to 'realloc', will cause the original memory block to be leaked.   dyn_arr_test   D:\projecten\C Programming\dyn_arr_test\dyn_arr_test.c   262      
Warning   C28183   'b' could be '0', and is a copy of the value found in 'realloc()`262':  this does not adhere to the specification for the function 'strcat'.    dyn_arr_test   D:\projecten\C Programming\dyn_arr_test\dyn_arr_test.c   263      


Because of these warnings, I asked ChatGPT how to get rid of the warnings. My hope was that a combination of the BCX code and some ChatGPT would build an even better code.

Now, this was not accomplished, but what are your thoughts about the above list of emitted warnings?

MrBcx

Hi Ad,

I looked at the code.  More importantly, I TESTED the code. 

It stinks!


I translated console sample S151.bas and then replaced CreateArr and DestroyArr with your code.

I needed to rename your two functions to match the BCX functions.

The modified S151.c compiles but when it is executed, it fails miserably.


ChatGPT can be really useful and it will tell you how great its code is but it is wrong more
times than it is correct.  With enough trial and error, you can nudge ChatGPT to make it
correct but you need to do the testing to ensure ChatGPT's code is working correctly. 
Its important to have a set of reliable code to test against.

I always test about 450 programs with multiple compilers before uploading each new
version of BCX.  And if you think that sounds tedious, you're right.   :D



Ad_Rienks

Together with ChatGPT, I have analysed the CreateArr & DestroyArr BCX functions to allocate Dynamic Arrays.
Please take a look at the example code that ChatGPT produced:


#include <stdio.h>
#include <stdlib.h>

// Prototype for destroy_arr
void destroy_arr(void** arr, int num_dims, int dim_size);

void* create_arr(void* dynavar, int elem_size, int update, int num_dims, size_t* args) {
    void** vp;
    size_t s1 = args[0];
    size_t s2 = args[1];
   
    if (num_dims == 1) {
        // If single dimension, allocate array of elements
        dynavar = calloc(s2, elem_size);
        if (!dynavar) return NULL; // Check for NULL after calloc

        // If update flag is set, initialize elements
        if (update) {
            for (size_t i = 0; i < s2; i++) {
                ((char*)dynavar)[i] = 0;
            }
        }
    } else {
        // Allocate array of pointers
        dynavar = calloc(s2, sizeof(void*));
        if (!dynavar) return NULL; // Check for NULL after calloc

        vp = (void**)dynavar;
        if (--num_dims > 0) {
            for (s1 = 0; s1 < s2; s1++) {
                vp[s1] = create_arr(NULL, elem_size, update, num_dims, args); // Recursive call with same args
                if (!vp[s1]) { // Clean up if allocation failed
                    while (s1 > 0) {
                        s1--;
                        destroy_arr((void**)vp[s1], num_dims + 1, s2);
                    }
                    free(dynavar);
                    return NULL;
                }
            }
        }
    }
    return dynavar;
}

void destroy_arr(void** arr, int num_dims, int dim_size) {
    if (num_dims == 1) {
        free(arr);
    } else {
        for (int i = 0; i < dim_size; i++) {
            if (arr[i]) {
                destroy_arr((void**)arr[i], num_dims - 1, dim_size);
            }
        }
        free(arr);
    }
}

int main() {
    size_t dimensions[2] = { (size_t)0, (size_t)BCXSTRSIZE };
    char** menu = (char**)create_arr(NULL, sizeof(char), 0, 2, dimensions);

    if (menu != NULL) {
        // Use menu here

        // Free menu when done
        destroy_arr((void**)menu, 2, BCXSTRSIZE);
    }

    return 0;
}



Quote
Explanation
Single Dimension Handling:

Allocate memory for an array of elements if num_dims == 1.
Initialize elements if update flag is set.
Multi-Dimension Handling:

Allocate memory for an array of pointers.
Recursively call create_arr for each element, reducing num_dims by 1.
Ensure proper cleanup if any allocation fails.
Destroy Function:

Implement destroy_arr to free memory recursively.
Summary
This refined version ensures proper handling of args and correct memory management for dynamic multi-dimensional arrays. Adjust the destroy_arr function and the recursive call parameters to maintain consistency and avoid potential buffer overruns or invalid reads.