Thread: Bsearch() isn't finding an integer key in my array.

  1. #1
    Registered User MilleniumFalcon's Avatar
    Join Date
    Feb 2014
    Posts
    33

    Bsearch() isn't finding an integer key in my array.

    I've been working at this for hours, but I can't figure out why bsearch() is not returning a key that's obviously in my array. Using my program's output as a debugging tool, I found that it compares garbage values four times and then returns NULL. I'm not sure what's happening to cause it. My array gets sorted into ascending order without incident, the bsearch() call seems to be where I'm running into problems. Even weirder, my other function call that searches for a string returns the expected value, even though it's almost identical to the one that's not working.

    Here is the code with the string search method included also.

    Code:
        static int CompareId( const void * a, const void * b )
        {
            processInfo * processA = ( processInfo * )a;
            processInfo * processB = ( processInfo * )b;
            cout << processA->pId << " " << processB->pId << END;
    
    
            return processA->pId - processB->pId;
        }
    
    
        static int CompareName( const void * a, const void * b )
        {
            processInfo * processA = ( processInfo * )a;
            processInfo * processB = ( processInfo * )b;
    
    
            return strcmp( processA->name, processB->name );
        }
    
        processInfo * FindProcess( int Id )
        {
            static processInfo process = { 0 };
            processInfo * temp = NULL;
    
    
            sortedByName = false;
    
    
            cout << "START" << END;
            if ( !processes )
                return NULL;
            if ( !sortedById )
                qsort( processes, processArrayInfo.elements, sizeof( *processes ), CompareId );
    
    
            cout << "SEARCH" << END;
            cout << processArrayInfo.elements << END;
            temp = ( processInfo * )bsearch( &Id, processes, processArrayInfo.elements, sizeof( *processes ), CompareId );
    
    
            if ( !temp )
                return NULL;
    
    
            cout << "END" << END;
            process = *temp;
            return &process;
        }
    
    
        processInfo * FindProcess( const char * name )
        {
            static processInfo process = { 0 };
            processInfo * temp = NULL;
    
    
            sortedByName = false;
    
    
            if ( !processes || !name )
                return NULL;
            if ( !sortedByName )
                qsort( processes, processArrayInfo.elements, sizeof( *processes ), CompareName );
    
    
            temp = ( processInfo * )bsearch( &name, processes, processArrayInfo.elements, sizeof( *processes ), CompareName );
    
    
            if ( !temp )
                return NULL;
    
    
            process = *temp;
            return &process;
        }
    Here is my main function:

    Code:
    int main( int argc, char ** argv )
    {
        systemSnapshot * snapshot = new systemSnapshot( );
    
    
        cout << "Taking system snapshot..." << END;
    
    
        if ( snapshot->TakeSnapshot( DEFAULT_SNAPSHOT ) )
            cout << "Success!" << END END;
        else
        {
            cout << "Failure!" << END END;
            return 1;
        }
    
    
        processInfo * explorer = snapshot->FindProcess(0);
        snapshot->PrintData( explorer );
    
    
        delete snapshot;
        return 0;
    }
    The output got truncated a bit, but here it is as it appears in my console:

    Code:
    4544 4480
    4376 4544
    4576 4544
    4840 4576
    4564 4840
    4828 4840
    4544 4480
    4376 4544
    4576 4544
    4828 4576
    4564 4828
    4544 4480
    4376 4544
    4576 4544
    4564 4576
    4544 4480
    4376 4544
    4564 4544
    4544 4480
    4376 4544
    4376 4480
    0 1580
    0 2604
    1580 2604
    4 1580
    256 1580
    380 1580
    456 1580
    512 1580
    528 1580
    536 1580
    700 1580
    776 1580
    824 1580
    900 1580
    956 1580
    272 1580
    388 1580
    492 1580
    1128 1580
    1332 1580
    1364 1580
    1516 1580
    1556 1580
    1612 1580
    1020 1580
    1664 1580
    1012 1580
    1732 1580
    2716 1580
    880 1580
    1772 1580
    2392 1580
    1600 1580
    2596 1580
    2800 1580
    2448 1580
    2352 1580
    2200 1580
    2124 1580
    2060 1580
    1432 1580
    1836 1580
    1928 1580
    1836 1580
    1432 1580
    1432 1580
    1836 2800
    1836 2604
    2800 2604
    1928 2604
    1772 2604
    2060 2604
    2124 2604
    2200 2604
    2352 2604
    2448 2604
    2596 2604
    1600 2604
    2392 2604
    1732 2604
    2716 2604
    1612 2604
    1664 2604
    2716 2604
    1664 2604
    1664 2604
    2800 2716
    1836 2448
    1836 1664
    2448 1836
    1928 1836
    1612 1836
    1772 1836
    2060 1836
    1732 1836
    2124 1836
    2392 1836
    1600 1836
    2200 1836
    2596 1836
    2604 1836
    2352 1836
    2352 1836
    1600 1836
    1612 1664
    1772 1664
    1732 1772
    1600 1772
    1612 1664
    1600 1664
    1732 1664
    1612 1664
    1600 1664
    1612 1600
    2352 2124
    2124 2448
    2352 2448
    2200 2352
    2604 2352
    1928 2352
    2596 2352
    2060 2352
    2392 2352
    2392 2352
    2060 2352
    2596 2392
    2604 2596
    2448 2604
    2596 2392
    2448 2596
    2448 2392
    2200 2124
    1928 2200
    2060 2200
    2060 2124
    1928 2124
    2060 1928
    0 272
    0 1432
    272 1432
    4 272
    256 272
    380 272
    880 272
    1012 272
    1020 272
    1580 272
    1556 272
    1516 272
    1364 272
    1332 272
    1128 272
    492 272
    388 272
    456 272
    956 272
    900 272
    824 272
    776 272
    700 272
    536 272
    528 272
    512 272
    456 272
    256 272
    4 0
    256 4
    4 0
    456 492
    456 1432
    492 1432
    512 492
    880 492
    1012 492
    1020 492
    1580 492
    1556 492
    1516 492
    1364 492
    1332 492
    1128 492
    528 492
    388 492
    536 492
    380 492
    700 492
    956 492
    900 492
    824 492
    776 492
    700 492
    380 492
    380 492
    492 456
    388 492
    380 492
    380 456
    388 456
    380 388
    700 1332
    700 1432
    1332 1432
    776 1332
    824 1332
    900 1332
    956 1332
    536 1332
    528 1332
    512 1332
    1128 1332
    1364 1332
    880 1332
    1516 1332
    1012 1332
    1556 1332
    1020 1332
    1580 1332
    1580 1332
    1020 1332
    1020 1332
    1556 1580
    1516 1580
    1364 1580
    1432 1580
    1556 1432
    1516 1556
    1364 1556
    1364 1432
    1516 1432
    1364 1432
    700 528
    528 1020
    700 1020
    776 700
    1012 700
    880 700
    1332 700
    1128 700
    512 700
    824 700
    900 700
    536 700
    956 700
    956 700
    536 700
    536 700
    512 528
    700 528
    536 700
    512 528
    536 528
    512 528
    956 1128
    956 1020
    1128 1020
    900 1020
    824 1020
    776 1020
    1332 1020
    1012 1020
    880 1020
    1332 1020
    880 1020
    880 1020
    1128 1332
    900 956
    824 956
    776 956
    1020 956
    1012 1020
    880 1020
    900 956
    824 956
    776 956
    880 956
    1012 956
    900 956
    824 956
    776 956
    880 956
    900 880
    824 900
    776 900
    776 880
    824 880
    776 824
    SEARCH
    68
    4645075 2060
    4645075 3552
    4645075 4828
    4645075 5352
    4645075 5732
    4645075 5940
    4645075 6060
    I'll post more if I have a reason to believe it's relevant. It uses win32, just like my previous post, but I already know that it is storing values correctly.

    Side note : I'm aware C++ has vectors that I can use with sort functions in the std namespace, but I didn't want to use them since my array won't be accessed that much.
    Last edited by MilleniumFalcon; 03-19-2014 at 05:04 PM.

  2. #2
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    How is that code not crashing?

    You just got insanely lucky that this didn't crash.

    o_O

    Well, maybe you'd have had more luck figuring the problem out if had of simply crashed.

    *shrug*

    Anyway, you can't use the same comparison function for `qsort' and `bsearch' the way you are using those functions.

    The `bsearch' function calls, for example, `CompareName' as `CompareName(&name, *processes)'; in other words, you don't really have a `processInfo'.

    You have two options: separating the sorting and searching comparator or putting the search key in a stack variable of the correct type.

    I would obviously advise the second approach.

    Code:
    processInfo sKey = {/* whatever */, name, /* whatever */};
    // ...
    temp = ( processInfo * )bsearch( &sKey, processes, processArrayInfo.elements, sizeof( *processes ), CompareName );
    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  3. #3
    Registered User MilleniumFalcon's Avatar
    Join Date
    Feb 2014
    Posts
    33
    Quote Originally Posted by phantomotap View Post
    O_o

    How is that code not crashing?

    You just got insanely lucky that this didn't crash.

    o_O

    Well, maybe you'd have had more luck figuring the problem out if had of simply crashed.

    *shrug*
    I have no idea, I ran it a billion times and debugged it on two different computers, it should've crashed. That makes sense of only the name finding being accurate, since that was the first field in my structure it would've stored the right address for comparison. As for the identifier search, hmm.

    I used the solution you recommended:

    Code:
    processInfo * FindProcess( int Id )
        {
            static processInfo process = { 0 };
            processInfo key = { NULL, Id, 0, 0, 0, NULL };
            processInfo * temp = NULL;
    
    
            sortedByName = false;
    
    
            if ( !processes )
                return NULL;
            if ( !sortedById )
                qsort( processes, processArrayInfo.elements, sizeof( *processes ), CompareId );
    
    
            temp = ( processInfo * )bsearch( &key, processes, processArrayInfo.elements, sizeof( *processes ), CompareId );
    
    
            if ( !temp )
                return NULL;
    
    
            process = *temp;
            return &process;
        }
    
    
        processInfo * FindProcess( const char * name )
        {
            static processInfo process = { 0 };
            processInfo key = { ( char * )name, 0, 0, 0, 0, NULL };
            processInfo * temp = NULL;
    
    
            sortedByName = false;
    
    
            if ( !processes || !name )
                return NULL;
            if ( !sortedByName )
                qsort( processes, processArrayInfo.elements, sizeof( *processes ), CompareName );
    
    
            temp = ( processInfo * )bsearch( &key, processes, processArrayInfo.elements, sizeof( *processes ), CompareName );
    
    
            if ( !temp )
                return NULL;
    
    
            process = *temp;
            return &process;
        }
    Code:
    Taking system snapshot...
    Success!
    
    
    Process image name : [System Process]
    Process identifier : 0
    Process parent identifier : 0
    Thread count : 2
    Thanks again!

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by MilleniumFalcon View Post
    Side note : I'm aware C++ has vectors that I can use with sort functions in the std namespace, but I didn't want to use them since my array won't be accessed that much.
    Wha? How does that make sense? You avoid vectors because your arrays aren't accessed so much? So? The strength of vectors does not lie in that they're faster to access or something.
    You could have saved yourself so much trouble if you just used std::vector, std::sort and std::string. Why didn't you? Why even allocate your snapshot on the heap? That makes no sense either.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Registered User MilleniumFalcon's Avatar
    Join Date
    Feb 2014
    Posts
    33
    Quote Originally Posted by Elysia View Post
    Wha? How does that make sense? You avoid vectors because your arrays aren't accessed so much? So? The strength of vectors does not lie in that they're faster to access or something.
    You could have saved yourself so much trouble if you just used std::vector, std::sort and std::string. Why didn't you? Why even allocate your snapshot on the heap? That makes no sense either.
    What do you mean "why did I allocate my snapshot on the heap", I need to store it internally in my class until the user deletes the object or takes another snapshot. That way the information the user can query using my class will be able to persist until it's not needed. It also needs to be dynamic to an extent because to my knowledge Microsoft doesn't provide a way to get the number of processes when I get the handle to the snapshot. Instead, I use a technique to allocate an array of 255 elements to start then keep increasing it by that size until the end of that function, where I decrease its' size to however many processes I was able to get information about via the handle. Usually 255 is much more than I'll need on the systems I've used it on, so that saves some allocation calls which can slow things down. Those are the main reasons why it's allocated on the heap.

    As far as a more in depth explanation of why I don't use vectors, well I'm not used to C++ exception handling to be honest. Anything with memory should obviously handle the major exceptions if something goes wrong, and I wasn't very comfortable traversing that territory. I could've learned it I suppose, but I didn't want to learn the C++ standard library for now since I'm more interested in the end program at this point. That and I've spent a lot more time with the C library, and I have very little experience with C++, although I learned the OOP concepts from C#. I would rather simply store a plain old array since my array interface handles all the work of allocation I need, without the potential overhead from C++ vectors. (They may be faster, that's just my guess)

    I don't see how std::string would've helped, strcmp() works fine.
    Last edited by MilleniumFalcon; 03-19-2014 at 06:22 PM.

  6. #6
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    @MilleniumFalcon:

    Look, I admit I didn't look over your posts much, but I believe them to be contain C code. You are going to keep getting comments like the one form Elysia as long as you continue to post C in the C++ forum.

    I don't know why you are having problems with "CodeBlocks"; I'd advise you to dump the install with a reinstall so that you can just compile your project correctly as C.

    Regardless, if you restrict yourself purely to C, you should post in the C forum.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by MilleniumFalcon View Post
    What do you mean "why did I allocate my snapshot on the heap", I need to store it internally in my class until the user deletes the object or takes another snapshot. That way the information the user can query using my class will be able to persist until it's not needed.
    In main, your class stays alive until the end of the function. Therefore, there is no need for "new" for your snapshot object.
    Furthermore, as long as your parent object is alive, all of its data is alive. Therefore, there is no need to store that on the heap, either.

    It also needs to be dynamic to an extent because to my knowledge Microsoft doesn't provide a way to get the number of processes when I get the handle to the snapshot. Instead, I use a technique to allocate an array of 255 elements to start then keep increasing it by that size until the end of that function, where I decrease its' size to however many processes I was able to get information about via the handle. Usually 255 is much more than I'll need on the systems I've used it on, so that saves some allocation calls which can slow things down. Those are the main reasons why it's allocated on the heap.
    Sounds like a good candidate for vectors.

    As far as a more in depth explanation of why I don't use vectors, well I'm not used to C++ exception handling to be honest. Anything with memory should obviously handle the major exceptions if something goes wrong, and I wasn't very comfortable traversing that territory. I could've learned it I suppose, but I didn't want to learn the C++ standard library for now since I'm more interested in the end program at this point. That and I've spent a lot more time with the C library, and I have very little experience with C++, although I learned the OOP concepts from C#. I would rather simply store a plain old array since my array interface handles all the work of allocation I need, without the potential overhead from C++ vectors. (They may be faster, that's just my guess)
    Stop worrying about efficiency.
    Stop worrying about the program.
    Start worrying about the bugs and other complexity you've introduced because you used low-level buildings blocks.
    Seriously, start learning a little C++. Experiment! You will learn that you don't need to be master to use a lot of C++'s building blocks.
    What is the point of using C++ if you're just going to use its C subset?

    I don't see how std::string would've helped, strcmp() works fine.
    Well, let's see...
    - No need for strcmp
    - No need for comparison functions (if you used std::sort)

    If you want to go further:
    - No risk for buffer overflows
    - Handy utility functions (e.g. substr)
    - Behaves like a real object (e.g. you can copy it, pass it by value, etc).
    - and more...
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    No need for comparison functions (if you used std::sort)
    O_o

    Why do you do this? Seriously, I need to know why you do this? C++ isn't magic, and you know it!

    You can proselytize without lying to people!

    He has two different forms of collation; he would still need two comparison functions.

    Furthermore, even if he had only one, he'd still have to code `operator <' so that `std::sort' would sort by the relevant key.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by phantomotap View Post
    Why do you do this? Seriously, I need to know why you do this? C++ isn't magic, and you know it!
    I can't see the full code. I can't see what the functions are trying to do.
    What is an ID? All I see are void* arguments.
    What I can see are the string comparisons, and for that, you don't need an extra comparison function, and that's what I wanted to point out with std::string.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Registered User MilleniumFalcon's Avatar
    Join Date
    Feb 2014
    Posts
    33
    @Phantomotap

    I'm not having problems with Code::Blocks in general, just for some reason their DLL project wizard doesn't give me the option to compile as C. There is probably a way around this, but I'm admittedly not an expert IDE user. As far as people like Elysia posting comments about my code, I don't mind it if they can persuade me to believe that method or technique is better than mine. I'm not using pure C, I used C++ in the main() function I posted, but if you didn't read that last part then I understand. If my techniques seem to be controversial on this forum, I might as well post my whole class to give people an idea of what I'm going for. I will include that at the end of this post.

    @Elysia

    I disagree that my code has "bugs and other complexity", I've spent a great deal of time restructuring it since my last post I made about goto. I think it's actually quite nice right now.

    As far as I know of, there is no standard for processes yet, so most of my functions will be win32 functions. I do use some C++ functions, like cout, but other than I don't really use them. I could start experimenting more, which I usually don't do near as much as I should, but I might wait until I have my program written. I may use vectors later, but I'm still not fully convinced I need them. I do agree with you on the issue of allocating my class on the heap, I misunderstood that a bit because I'm used to having to use new in C# for classes.

    The Id variable is an integer, which you can see in my function declaration. I'm not using "void * arguments" to those. It represents the identifier for a Windows process, and actually that's not even unique to just Windows anyways. You might have a point on the std::sting class, but I can't say for sure since I haven't used it yet.

    Code:
    class systemSnapshot
    {
    
    
    private:
        array_t processArrayInfo;
        processInfo * processes;
    
    
        HANDLE snapshot;
        PROCESSENTRY32 entry;
    
    
        bool sortedByName;
        bool sortedById;
    
    
        void DestroyModuleResources( moduleInfo * modules, int arraySize )
        {
            if ( modules )
            {
                for ( int i = 0; i < arraySize; ++i )
                    if ( modules[i].name )
                        free( modules[i].name );
    
    
                free( modules );
            }
        }
    
    
        void DestroyProcessResources( processInfo * processes, int arraySize )
        {
            if ( processes )
            {
                for ( int i = 0; i < arraySize; ++i )
                    if ( processes[i].name )
                        free( processes[i].name );
    
    
                free( processes );
            }
        }
    
    
        void DestroyResources( )
        {
            sortedById = false;
            sortedByName = false;
    
    
            for ( int i = 0; i < processArrayInfo.elements; ++i )
                DestroyModuleResources( processes[i].modules, processes[i].moduleCount );
    
    
            DestroyProcessResources( processes, processArrayInfo.elements );
            processes = NULL;
    
    
            if ( snapshot != INVALID_HANDLE_VALUE )
                CloseHandle( snapshot );
        }
    
    
        bool CreateSnapshot( )
        {
            snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
    
    
            return snapshot != INVALID_HANDLE_VALUE;
        }
    
    
        bool GetFirstProcessEntry( )
        {
            entry.dwSize = sizeof( PROCESSENTRY32 );
            bool status = Process32First( snapshot, &entry );
    
    
            if ( !status )
            {
                showWindowsError( "Process32First()", false );
                DestroyResources( );
            }
    
    
            return status;
        }
    
    
        bool SetExecutableName( processInfo * process, const char * name )
        {
            process->name = copyString( name );
    
    
            if ( !name )
                DestroyResources( );
    
    
            return name != NULL;
        }
    
    
        bool CreateProcessArray( )
        {
            processArrayInfo.memory = ( processInfo * )createArray( &processArrayInfo, DEFAULT_ELEMENTS, sizeof( processInfo ), zeroArray );
    
    
            if ( !processArrayInfo.memory )
                DestroyResources( );
    
    
            return processArrayInfo.memory != NULL;
        }
    
    
        bool IncreaseProcessArraySize( )
        {
            processArrayInfo.memory = ( processInfo * )increaseArraySize( &processArrayInfo, DEFAULT_ELEMENTS );
    
    
            if ( !processArrayInfo.memory )
                DestroyResources( );
    
    
            return processArrayInfo.memory != NULL;
        }
    
    
        bool ResizeProcessArrayTo( int arraySize )
        {
            processArrayInfo.elements = arraySize;
            processArrayInfo.memory = resizeArray( &processArrayInfo );
    
    
            if ( !processArrayInfo.memory )
                DestroyResources( );
    
    
            return processArrayInfo.memory != NULL;
        }
    
    
        static int CompareId( const void * a, const void * b )
        {
            processInfo * processA = ( processInfo * )a;
            processInfo * processB = ( processInfo * )b;
    
    
            return processA->pId - processB->pId;
        }
    
    
        static int CompareName( const void * a, const void * b )
        {
            processInfo * processA = ( processInfo * )a;
            processInfo * processB = ( processInfo * )b;
    
    
            return strcmp( processA->name, processB->name );
        }
    
    
    public :
        systemSnapshot( )
        {
            memset( ( void * )&processArrayInfo, 0, sizeof( array_t ) );
            processes = NULL;
            sortedById = false;
            sortedByName = false;
        }
    
    
        bool TakeSnapshot( int flags )
        {
            int processCount = 0;
    
    
            if ( processes )
                DestroyResources( );
    
    
            if ( !CreateSnapshot( ) )
                return false;
            if ( !GetFirstProcessEntry( ) )
                return false;
            if ( !CreateProcessArray( ) )
                return false;
    
    
            do
            {
                processes = ( processInfo * )processArrayInfo.memory;
                processes[processCount].pId = entry.th32ProcessID;
                processes[processCount].parentPId = entry.th32ParentProcessID;
                processes[processCount].threadCount = entry.cntThreads;
                processes[processCount].modules = NULL;
    
    
                if ( flags & SAVE_MODULE_INFORMATION );
                    /* TODO : Add code to save information for process modules */
    
    
                if ( !SetExecutableName( &processes[processCount], entry.szExeFile ) )
                    return false;
    
    
                if ( ++processCount >= processArrayInfo.elements - 1 )
                    if ( !IncreaseProcessArraySize( ) )
                        return false;
    
    
            } while ( Process32Next( snapshot, &entry ) );
    
    
            if ( !ResizeProcessArrayTo( processCount ) )
                return false;
    
    
            CloseHandle( snapshot );
            snapshot = INVALID_HANDLE_VALUE;
            return true;
        }
    
    
        processInfo * FindProcess( int Id )
        {
            static processInfo process = { 0 };
            processInfo key = { NULL, Id, 0, 0, 0, NULL };
            processInfo * temp = NULL;
    
    
            sortedByName = false;
    
    
            if ( !processes )
                return NULL;
            if ( !sortedById )
                qsort( processes, processArrayInfo.elements, sizeof( *processes ), CompareId );
    
    
            temp = ( processInfo * )bsearch( &key, processes, processArrayInfo.elements, sizeof( *processes ), CompareId );
    
    
            if ( !temp )
                return NULL;
    
    
            process = *temp;
            return &process;
        }
    
    
        processInfo * FindProcess( const char * name )
        {
            static processInfo process = { 0 };
            processInfo key = { ( char * )name, 0, 0, 0, 0, NULL };
            processInfo * temp = NULL;
    
    
            sortedByName = false;
    
    
            if ( !processes || !name )
                return NULL;
            if ( !sortedByName )
                qsort( processes, processArrayInfo.elements, sizeof( *processes ), CompareName );
    
    
            temp = ( processInfo * )bsearch( &key, processes, processArrayInfo.elements, sizeof( *processes ), CompareName );
    
    
            if ( !temp )
                return NULL;
    
    
            process = *temp;
            return &process;
        }
    
    
        void PrintData( )
        {
            for ( int i = 0; i < processArrayInfo.elements; ++i )
            {
                cout << END << "Process #" << ( i + 1 ) << END;
                cout << "Process image name : " << processes[i].name << END;
                cout << "Process identifier : " << processes[i].pId << END;
                cout << "Process parent identifier : " << processes[i].parentPId << END;
                cout << "Thread count : " << processes[i].threadCount << END;
            }
        }
    
    
        void PrintData( processInfo * process )
        {
            if ( !process )
                return;
    
    
            cout << "Process image name : " << process->name << END;
            cout << "Process identifier : " << process->pId << END;
            cout << "Process parent identifier : " << process->parentPId << END;
            cout << "Thread count : " << process->threadCount << END;
        }
    
    
        ~systemSnapshot( )
        {
            DestroyResources();
        }
    };
    Here's some extra declarations :

    Code:
        typedef struct moduleInfo
        {
            char * name;
            int baseAddress;
            int sizeBytes;
        } moduleInfo;
    
    
        typedef struct processInfo
        {
            char * name;
    
    
            int pId;
            int parentPId;
            int threadCount;
            int moduleCount;
    
    
            moduleInfo * modules;
        } processInfo;
    
    
        enum
        {
            DEFAULT_SNAPSHOT = 0x1,
            SAVE_MODULE_INFORMATION = 0x2
        };
    
    
        #define DEFAULT_ELEMENTS 255
    I know people may complain about my code since it's using win32 functions, but I'm posting it to show how I wrote the class to prove my point. Otherwise I wouldn't have posted it, since I'm not a big fan of dumping the majority of my program online for everyone.
    Last edited by MilleniumFalcon; 03-20-2014 at 02:53 PM.

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by MilleniumFalcon View Post
    I disagree that my code has "bugs and other complexity", I've spent a great deal of time restructuring it since my last post I made about goto. I think it's actually quite nice right now.

    As far as I know of, there is no standard for processes yet, so most of my functions will be win32 functions. I do use some C++ functions, like cout, but other than I don't really use them. I could start experimenting more, which I usually don't do near as much as I should, but I might wait until I have my program written. I may use vectors later, but I'm still not fully convinced I need them. I do agree with you on the issue of allocating my class on the heap, I misunderstood that a bit because I'm used to having to use new in C# for classes.
    You don't need vectors, but they certainly help.

    I took a look at your code, and saw that if you used std::string and std::vector, you could probably get rid of the functions (I only analysed TakeSnapshot):

    DestroyResources
    SystemSnapshot Destructor (if you wrap your handles in some RAII class that closes them automatically)
    DestroyModuleResources
    DestroyProcessResources
    createArray
    increaseArraySize
    CreateProcessArray
    IncreaseProcessArraySize
    ResizeProcessArrayTo
    resizeArray

    Yes, that's a lot! so much complexity would be removed "simply" by using std::string and std::vector.
    You would still need to close your handle(s), but other than that, you're free.

    Would you still claim your code is not complex?

    EDIT: I should not bark at people.
    Last edited by Elysia; 03-20-2014 at 03:10 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Registered User MilleniumFalcon's Avatar
    Join Date
    Feb 2014
    Posts
    33
    Well I suppose that complexity is very subjective, so the fact that I'm experienced with C may obscure my vision as far as what C++ may be capable of.

    As far as getting rid of that many functions, that seems like pure witchcraft to me. I could agree that vectors would make my array functions implementation obsolete, but I don't see why the resources functions would all be obsolete. Even if I could do something like "myVector.clear()" and automatically get rid of the elements related to the vector, I still have strings and in the future modules to handle freeing. I would also still need wrappers to make sure the resources are freed if an exception is thrown by the vector, because it could get messy to handle that all in TakeSnapshot().

    If I can really get rid of all of the functions you think that I can, I'll move to your C++ side. Otherwise, I'll probably just stay on my C style side.

  13. #13
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Quote Originally Posted by MilleniumFalcon View Post
    As far as getting rid of that many functions, that seems like pure witchcraft to me. I could agree that vectors would make my array functions implementation obsolete, but I don't see why the resources functions would all be obsolete. Even if I could do something like "myVector.clear()" and automatically get rid of the elements related to the vector, I still have strings and in the future modules to handle freeing.
    std::string will free itself just fine when it goes out of scope. You don't need to do anything about that.

    I would also still need wrappers to make sure the resources are freed if an exception is thrown by the vector, because it could get messy to handle that all in TakeSnapshot().
    You'd use the RAII pattern to make a class that manages your resource. Its destructor will free the resources, regardless of how the variable goes out of scope. If you're using good design patterns in C++, basic exception safety (no-leak safety) is actually pretty simple. It's when you're not using good idioms that it becomes a challenge.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  14. #14
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    "It is a poor workman who blames his tools."

    You should know enough to "save as" a file in Code::Blocks (CB).
    If not, learn how to do it.
    Change the file extension from the wizard to c instead of cpp.
    Add the new file; remove the old file.
    Remove the [extern "C"], you now have a C DLL that you can save as a CB template.

    Tim S.

    Quote Originally Posted by MilleniumFalcon View Post
    @Phantomotap

    I'm not having problems with Code::Blocks in general, just for some reason their DLL project wizard doesn't give me the option to compile as C. There is probably a way around this, but I'm admittedly not an expert IDE user. As far as people like Elysia posting comments about my code, I don't mind it if they can persuade me to believe that method or technique is better than mine. I'm not using pure C, I used C++ in the main() function I posted, but if you didn't read that last part then I understand. If my techniques seem to be controversial on this forum, I might as well post my whole class to give people an idea of what I'm going for. I will include that at the end of this post.
    Last edited by stahta01; 03-22-2014 at 07:34 AM.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  15. #15
    Registered User MilleniumFalcon's Avatar
    Join Date
    Feb 2014
    Posts
    33
    Quote Originally Posted by stahta01 View Post
    "It is a poor workman who blames his tools."

    You should know enough to "save as" a file in Code::Blocks (CB).
    If not, learn how to do it.
    Change the file extension from the wizard to c instead of cpp.
    Add the new file; remove the old file.
    Remove the [extern "C"], you now have a C DLL that you can save as a CB template.

    Tim S.
    I've done that before, but I've never been sure if the IDE actually detects that and changes the compilation process or not. I'm not clueless about how to use Code::Blocks.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 10
    Last Post: 05-15-2011, 06:52 PM
  2. Finding next largest integer multiple
    By trinitrotoluene in forum C Programming
    Replies: 2
    Last Post: 06-16-2010, 05:48 PM
  3. Finding # of digits in an integer
    By Canucklehead in forum C++ Programming
    Replies: 4
    Last Post: 10-16-2005, 12:54 AM
  4. Finding the Mode of an integer array
    By -]SC[-Dargoth in forum C++ Programming
    Replies: 4
    Last Post: 07-28-2003, 02:27 PM
  5. finding an integer in an integer
    By Unregistered in forum C++ Programming
    Replies: 5
    Last Post: 05-09-2002, 07:25 PM