Return pointer from void only gives the memory address

Joined
Nov 23, 2024
Messages
1
Reaction score
0
Good day,

I want to build some wrapper .dll and part of it is to extract data from a void function and pass it on. So its possible to pass something vi a pointer or a global value. But with *(& fptr) I can only get the address of the variable, whereas inside the function *(& fptr) actually returns the value of the variable.
Yet In the debugger the memory address contains the value until the last line, return (); , so it should still be there at sdt::cout

What else needs doing?


Code:
#include <iostream>
double voidfilled1{};

void* pointer(double inptr)
{
    double voidFunctPtr{};
    voidFunctPtr = inptr+3;
    std::cout << "inside funct is float: " << voidFunctPtr << ", &voidFunctPtr: "<<  &voidFunctPtr << ", *(&voidFunctPtr) :"<< *(&voidFunctPtr) << '\n';
    voidfilled1 = voidFunctPtr;
    return &voidFunctPtr;
}

int main() {

    double ptr{3.3};
    double* fptr = (double*) pointer(4.6+4);
    double retrieved{};
    std::cout << "content of main is " << ptr << " in funct: "<< &fptr << " global: "<< voidfilled1 << " *(&fptr):" << *(& fptr) << '\n';
    return 0;
}

yields this. But *(& fptr) should yield 11.6?

inside funct is float: 11.6, &voidFunctPtr: 000000A11E2FF7E8, *(&voidFunctPtr) :11.6
content of main is 3.3 in funct: 000000A11E2FF928 global: 11.6 *(& fptr):000000A11E2FF7E8
 
Joined
Jun 12, 2020
Messages
60
Reaction score
3
To address your question about passing data from a void function and using pointers effectively, I received valuable assistance from a generative AI. It's important to note that returning a pointer to a local variable can lead to undefined behavior since that variable goes out of scope once the function exits. Instead of returning a pointer, consider utilizing a more robust implementation, such as the SecureBuffer class provided in the suggested code.
This class manages memory safely by using std::vector to store values securely, allowing you to write and read data with built-in bounds checking. It ensures that sensitive information is erased upon destruction, enhancing security. Additionally, the Calculator class facilitates safe computations with input validation and bounds checking, which helps prevent potential errors.
Integrating these structures provides a safer alternative for managing data flow and will help you avoid the issues you're encountering with pointers. This approach enables you to maintain and pass on data effectively, without risking undefined behavior or memory-related bugs.

C++:
#include <iostream>
#include <vector>
#include <cstdint>
#include <optional>
#include <stdexcept>
#include <iomanip>
#include <cstring>   // Include for memcpy
#include <cmath>     // Include for isfinite

// Improved SecureBuffer using std::vector for automatic memory management
class SecureBuffer {
private:
    std::vector<std::uint8_t> buffer; // Use vector for automatic resource management
    size_t dataSize;

public:
    // Constructor with automatic zero-initialization
    explicit SecureBuffer(size_t sz) : buffer(sz, 0), dataSize(sz) {}

    // Secure write with bounds checking and exception handling
    void writeSecure(size_t offset, double value) {
        if (offset + sizeof(double) > dataSize) {
            throw std::out_of_range("Write offset exceeds buffer bounds");
        }
        std::memcpy(buffer.data() + offset, &value, sizeof(double));
    }

    // Secure read with bounds checking
    std::optional<double> readSecure(size_t offset) const {
        if (offset + sizeof(double) > dataSize) {
            return std::nullopt;
        }
        double value;
        std::memcpy(&value, buffer.data() + offset, sizeof(double));
        return value;
    }

    // Secure erasure before destruction
    ~SecureBuffer() {
        secureErase();
    }

    // Explicit secure erase method
    void secureErase() {
        std::fill(buffer.begin(), buffer.end(), 0); // Ensure sensitive data is erased
    }

    // Get buffer size for debugging/logging
    size_t getSize() const { return dataSize; }
};

// Improved Calculator with enhanced bounds checking and validation
class Calculator {
private:
    double result{0.0};

public:
    // Enhanced compute with input validation
    double compute(double input, double adjustment) {
        // Validate inputs
        if (!std::isfinite(input) || !std::isfinite(adjustment)) {
            throw std::invalid_argument("Input values must be finite numbers");
        }
        double computed = input + adjustment;

        if (computed < -1000.0 || computed > 1000.0) {
            throw std::out_of_range("Computed result exceeds safe bounds [-1000, 1000]");
        }

        result = computed; // Store computed result
        return result;
    }

    double getResult() const {
        return result;
    }

    // Reset calculator
    void reset() {
        result = 0.0; // Clear the result for fresh computations
    }
};

int main() {
    try {
        double ptr = 3.3;
        double adjustment = 3.0;

        // Use RAII for automatic resource management
        SecureBuffer secureBuffer(sizeof(double));
        Calculator calculator;

        std::cout << std::fixed << std::setprecision(2);
        
        // Print memory addresses for debugging
        std::cout << "=== Memory Layout ===\n";
        std::cout << "Address of ptr: " << &ptr << '\n';
        std::cout << "Address of adjustment: " << &adjustment << '\n';
        std::cout << "Address of secureBuffer: " << &secureBuffer << '\n';
        std::cout << "Address of calculator: " << &calculator << '\n';
        std::cout << "SecureBuffer size: " << secureBuffer.getSize() << " bytes\n\n";

        // Perform secure computation
        std::cout << "=== Computation ===\n";
        double inputValue = 4.6 + 4.0; // 8.6
        std::cout << "Input value: " << inputValue << '\n';
        std::cout << "Adjustment: " << adjustment << '\n';

        double computedResult = calculator.compute(inputValue, adjustment);
        std::cout << "Computed result: " << computedResult << '\n';
        std::cout << "Calculator result: " << calculator.getResult() << "\n\n";

        // Secure storage and retrieval
        std::cout << "=== Secure Storage ===\n";
        secureBuffer.writeSecure(0, computedResult);
        std::cout << "Secure value written to buffer successfully.\n";

        auto retrievedValue = secureBuffer.readSecure(0);
        if (retrievedValue) {
            std::cout << "Retrieved secure value: " << *retrievedValue << '\n';
            std::cout << "Verification: Stored == Retrieved: "
                      << std::boolalpha << (computedResult == *retrievedValue) << '\n';
        } else {
            std::cerr << "Failed to retrieve secure value.\n";
        }

        std::cout << "\n=== Final State ===\n";
        std::cout << "Local ptr value: " << ptr << '\n';
        std::cout << "Calculator result: " << calculator.getResult() << '\n';
        std::cout << "Secure buffer automatically erased on destruction.\n";

    } catch (const std::out_of_range& e) {
        std::cerr << "Out of bounds error: " << e.what() << '\n';
        return -1;
    } catch (const std::invalid_argument& e) {
        std::cerr << "Invalid argument error: " << e.what() << '\n';
        return -2;
    } catch (const std::exception& e) {
        std::cerr << "Unexpected error: " << e.what() << '\n';
        return -3;
    } catch (...) {
        std::cerr << "Unknown error occurred.\n";
        return -4;
    }

    std::cout << "\nProgram completed successfully.\n";
    return 0;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top