I don't think that you "need" OOP for anything. The question is can it make your life easier. The problem is that there are a ton of debates on what OOP is and how to use it.
On a basic level, I think classes in general give you a better namespace. In C it does get a bit tiresome to start naming functions My_Company_My_Module_FunctionA() and objects/namespaces can save some typing. Then you just get a reference to a class c and can just be like c.FunctionA(), c.FunctionB()....
Another note is containers. Often object oriented languages provide more generic libraries for stacks/queues/etc... C++ in particular has templates. So instead of needing to code something with void pointers, or different versions for different datatypes, you can just have one list/stack/etc class. which handles every datatype. In most C programs that I look at, I see multiple implementations of linked lists as opposed to making a single implementation and then recycling that. In C++ you actually get the Standard Template Library which contains many collections (along with algorithms to manipulate them). I would say the STL implementations/algorithms are more likely to be correct than a home grown set, especially if you have multiple implementations of them spread throughout the code.
Also a lot of C programs have if/switch statements all over the program. E.g. you have a program to process different messages and various functions ProcessHeader, ProcessBody, etc. and tons of sub-functions. All over the program you switch (or use if statements) based on message types because different messages have different formats. Now you add a new type...where do you make the change? You need to go through all those functions and review them. If you used OOP and factored the code correctly, you could get by just adding a new message class (which inherits from some generic class with a ProcessHeader/ProcessBody/etc..) that you override. Then all over the place the code does not need an if/switch statement. Instead it can ask the generic object to perform whatever operation and then each message type object can decide how to do it..... In addition to reducing errors and making the changes required for new items in a single place, it also makes it easier to identify where to make changes. When things are scattered it is often hard to find where you need to make a change...
One thing about C++ (not necessarily oop) is exceptions. You mentioned that you need to handle errors. In C error handling is tough. Functions return error values that have to be checked everywhere. Sometimes you even need to consult errno. The good thing about exceptions is that you can bubble them up. Sometimes if a really low level function has an error there isn't much you can do to recover at that level. Maybe you'll need to return/process an error through 4 or 5 functions before getting to a level where you can recover. With exceptions you can just throw an exception and instead of having error checking code in those lower level functions you can catch/handle it at a higher level...
Also the other thing is that it is possible to use OOP in C. You can code with an OOP style (which a lot of the more maintainable C is). It all comes down to encapsulation. After all, if you use structs to hold data, and a bunch of functions to manipulate those structs in your different modules and then only use those functions to access the data....then basically you are coding an "object" in C. If you are externing global variables all over the place, then that is harder to maintain. But for smaller programs it is fine...
In any case, I think you need to explore both OOP and the various approaches to it (design patterns, object thinking (behavior oriented object design), data based thinking, etc.... You may be managing fine in a non object oriented way, but unless you explore the object oriented way, you'll never know if it can simplify your life. One major change between an object oriented program and a non object oriented program is the control. In a procedural program often there are some methods that control a bunch of other methods (either a main loop or a main section of a module) while in an object oriented program often the control is delegated around a lot more (which actually leads to better decomposition in some cases). Still it's all a balance.
In short, I would be surprised if you did not find something useful from either OOP or even just C++ (I'm thinking exceptions would probably benefit you and simplify some code...but again I'm not sure).
On one job I remember that I was having trouble making a web interface. It had all of these individual text boxes along with a bunch of rules about filling them in. Generally I do write things procedurally. But in that case I made an object for the box and the collection of boxes. I charged the object with converting the structure to HTML and from HTML into an array. The collection object told each individual box to handle itself. Overall when done it was much cleaner and easier for me to manage mentally. Still I am not an OOP expert. But the very thing that made the mess of a screen manageable to me (delegating the control to these sub objects) seems to be the main benefit of OOP advertised by a number of sources.
Also there is a lot of bad OOP code out there. There are all sorts of poor inheritance hierarchies (one of the reasons the design patterns book advises favoring composition over inheritance).... Also people throwing in objects for fun and writing mostly procedural code (like I do most of the time). But the real OOP seems to be about letting objects be responsible for themselves. Instead of a method doing a bunch of steps and checking each step to see if it was done, you call objects which do things and they are responsible to do it right or report their failure...
For example you have a data loader. If you had really different file types, you might have a DataLoader object and tell it to LoadFiles. Also if you are always talking to the same database, you may have an object DataBase responsible for connecting to the database, hitting it with queries, returning data, and doing all the error handling. If you always follow a prescribed set of steps, DataLoader might define the steps and even a routine to perform the steps in the right order, and then you might subclass DataLoader to actually perform the steps for each file type.... But overall I don't know.... It really depends on your situation. Also you don't need to go all OOP at once. If you have some piece of code with more defects then the others, you might think of how you might model that as a set of objects and how to break up the responsibility/control....