Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
newsomnuke
Feb 25, 2007

Vanadium posted:

T sum = T(); should work in all cases I can think of.
What about matrices? Mightn't they be constructed to the identity matrix, rather than all zeros? Is there a more standard method which doesn't rely on the implementation of the type?

Adbot
ADBOT LOVES YOU

Vanadium
Jan 8, 2005

ultra-inquisitor posted:

What about matrices? Mightn't they be constructed to the identity matrix, rather than all zeros? Is there a more standard method which doesn't rely on the implementation of the type?

I can write a type that responds to any specific attempt to initialise it by blowing up your harddrive, so I doubt it. :(

BigRedDot
Mar 6, 2008

Ledneh, you can give them an interface that allows them to pass in whatever they want. Something like this (untested) code:
code:
// This should automagically work with boost function objects, C functions, functor objects, or static methods
void SetCallback( boost::function1<void, int> func) {
    // just store the boost function object
}


// And this will work for member functions
template <typename T>
void SetCallback( void (T::*func)(int), T * obj ) {
    // bind func and obj and use the first function to store
    SetCallback( boost::bind( func, obj, _1 ) );
}

This way people can supply whatever kind of thing they want as a call back, and they don't have to use boost directly if they don't want to:
code:
void cb( int i ) { ; }
SetCallback( cb );

struct Functor { 
    void operator( )( int i ) { ; }
};
Functor cb_functor;
SetCallback( cb_functor );

class Handler {
   void DoStuff( int i ) { ; }
};
Handler * obj = new Handler;
SetCallback( &Handler::DoStuff, obj );

class OtherHandler {
   void DoOtherStuff( int i ) { ; }
};
OtherHandler * other_obj = new OtherHandler;
SetCallback( &OtherHandler::DoOtherStuff, other_obj );

// Note, in particular, that this will be rejected by the compiler (which is what you want):
//SetCallback( &Handler::DoStuff, other_obj );
I will add one caveat: these methods are going to involve an extra indirection. So if these callbacks are in the middle of some performance-sensitive inner loop or something, then they could possibly be too slow for your needs. OTOH if you were talking about being in the middle of a performance-sensitive inner loop, you probably wouldn't be using class methods of any kind in any case.

BigRedDot fucked around with this message at 21:06 on Dec 4, 2008

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


Thanks BigRedDot, that looks like a solution I can make work. Didn't occur to me to try templating setCallback. :downs:

(edit) As far as performance goes, it's not a real-time project, and I've always been taught never to optimize as I go anyway (with the "unless it's totally obvious" caveat of course). So one extra indirection doesn't bother me at all.

Ciaphas fucked around with this message at 21:14 on Dec 4, 2008

The Red Baron
Jan 10, 2005

ultra-inquisitor posted:

What about matrices? Mightn't they be constructed to the identity matrix, rather than all zeros? Is there a more standard method which doesn't rely on the implementation of the type?

If this is a concern, just provide the initial value as a default parameter

code:
template <typename T>
T sumArray (const vector<T> &arr, T init = T())
{
	for (size_t i = 0; i < arr.size (); ++i)
		init += arr[i];

	return init;
}

newsomnuke
Feb 25, 2007

The Red Baron posted:

If this is a concern, just provide the initial value as a default parameter

code:
template <typename T>
T sumArray (const vector<T> &arr, T init = T())
{
	for (size_t i = 0; i < arr.size (); ++i)
		init += arr[i];

	return init;
}
It's just for my own edification, I was wondering if there was some cool language feature I didn't know about that might facilitate it. I'm still pretty inexperienced at generic programming.

Zombywuf
Mar 29, 2008

Ledneh posted:

The second is the same way, except I count on the rest of the team to use boost::bind where needed. Cleaner and less error-prone for me, and probably more type-safe, but the rest of the group has to learn how (and remember) to use boost::bind.

Function object adapters are part of the STL, and boost::bind is easier to use than the standard ones so I wouldn't worry about the rest of the group.

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


BigRedDot, I implemented your solution in my test bed, and it works great, but I have one question. I was discussing this elsewhere too, and the question came up as to whether or not for your templated SetCallback you have to include a template parameter.

My compiler (Sun CC) can get away with SetCallback(Type::blah, obj), but someone else reported their compiler giving up until they did SetCallback<Type>(Type::blah, obj). I assume you're supposed to have to specify the template parameter explicitly?

Zombywuf
Mar 29, 2008

Ledneh posted:

BigRedDot, I implemented your solution in my test bed, and it works great, but I have one question. I was discussing this elsewhere too, and the question came up as to whether or not for your templated SetCallback you have to include a template parameter.

My compiler (Sun CC) can get away with SetCallback(Type::blah, obj), but someone else reported their compiler giving up until they did SetCallback<Type>(Type::blah, obj). I assume you're supposed to have to specify the template parameter explicitly?

You should only have to do that if the type is not present in the function arguments, i.e.:
code:
template<class T>
T f(int a) { ... }
f<T>(x) // must be called like this

template<class T>
T f(T a) { ... }
f(x) // can be called like this

template<class T, class S>
T f(S a) { ... }
f<T>(x) // can be called like this

BigRedDot
Mar 6, 2008

No I don't think you should need to. I use some almost identical code to set up some middleware callbacks. We use various versions of gcc, and I never have to specify the template parameter explicitly. I use code just like what I posted above with Handler and OtherHandler.

What compiler is complaining?

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


(edit) "MSVC 2008 with service pack 1"

In the meantime, another question. Right now the relevant bits of my real-world class look like this:
code:
template <class T>
class CDataContainer
{
public:
  // ...
  typedef boost::function<void(const CDataRecord<T>&)> TOutputFunc;
  // ...
  void setOutputCallback(TOutputFunc func)
  {
    mOutputFunc = func; 
  }

  template <class U>
  void setOutputCallback(void (U::*func)(const CDataRecord<T>&), U* obj)
  {
    mOutputFunc = boost::bind(func, obj, _1);
  }
};
As you can see, the second setOutputCallback() has the full form of the function pointer, which is a problem because if I have to change the typedef'd boost::function, I have to remember to change setOutputCallback(), too, which kind of renders typedeffing in the first place sort of moot. I tried setting up a second typedef like this:
code:
template <class T>
class CDataContainer
{
public:
  // ...
  template <class U>
  typedef void (U::*TOutputFunc2)(const CDataRecord<T>&);
  // ...
};
so that I could at least have them together to make it easier to keep synced, but it didn't take, with an error about templated typedefs being an anachronism. Is there anything I can do about this, or am I more or less stuck? The Internet At Large seems to imply that I'm stuck :(

Ciaphas fucked around with this message at 23:00 on Dec 4, 2008

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

Ledneh posted:

so that I could at least have them together to make it easier to keep synced, but it didn't take, with an error about templated typedefs being an anachronism. Is there anything I can do about this, or am I more or less stuck?

Template typedefs don't exist, and they won't until the next standard.* Just make the second overloaded version call the first, which should pick up any errors. i.e.

code:
template <class U>
void setOutputCallback(void (U::*func)(const CDataRecord<T>&), U* obj)
{
    setOutputCallback( boost::bind(func,obj,_1) );
}
* Sort of.

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


Youse a drat genius. Or I'm just dumb as a rock. Either way, thanks muchly :)

(edit) so it does. I guess this proves that the latter statement is true at least :saddowns:
|
V

Ciaphas fucked around with this message at 00:10 on Dec 5, 2008

BigRedDot
Mar 6, 2008

Ledneh, what AD shows is what I had up in the example I posted, and what I use in my own code at work.

As for the compiler, I haven't done any windows development since 1995, so I really don't know anything at all about MSVC. Maybe someone else can speak to its quirks and peccadilloes.

Night Chaos
Jun 8, 2003

So the IRC krew knows I have been having a little trouble with yacc, trying to parse a small subset of Verilog.

I need to change the type of yylval to char * so I can store string tokens in it and grab those in the parser. My productions work, I just need to change yylval from it's default type of int to char *.

I have tried #define YYSTYPE char *

and extern YYSTYPE yylval;

I know I have to do something like that somewhere, whenever I put that in however yacc tells me

code:
y.tab.h:86: error: previous declaration of ‘yylval’ was here
obviously the extern YYSTYPE yylval is still there.


So basically, I just need to know how to declare yylval properly.

Here is my scanner - http://rafb.net/p/Qm8ANp74.html
and my grammar - http://rafb.net/p/dI1Iu111.html

Night Chaos fucked around with this message at 00:44 on Dec 5, 2008

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
You're doin' it wrong. #define YYSTYPE char * goes in the yacc file, not the lex file.

Night Chaos
Jun 8, 2003

That problem fixed, why now will everything parse properly except my gates.

http://filer.case.edu/dsu/vparse.tar

Makefile and test input file included, it'll do everything except gates, and I can't see why.

Somebody could look at my grammar productions with fresh eyes and see some missing token or something?

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
You're trying to print the yylval of the gate type and you aren't specifying a yylval in the lexer. Either strdup the yytext for all your gates or make different productions for each gate type.

DontMockMySmock
Aug 9, 2008

I got this title for the dumbest fucking possible take on sea shanties. Specifically, I derailed the meme thread because sailors in the 18th century weren't woke enough for me, and you shouldn't sing sea shanties. In fact, don't have any fun ever.
code:
#define nfreq 90
float chisquared(float coef, float index, float pixel[nfreq],float fq[nfreq]){
  float sum=0;
  int i=0;
  for(i=0;i<nfreq;i++) {
    sum=sum+(pow(pixel[i]-coef*pow(fq[i],index),2))/(coef*pow(fq[i],index));
    }
  return sum;
}
Given that all of the input variables are always positive and nonzero, how could this code ever return NaN? Because it does, all the time.
The only thing I could figure was if fq was ever negative and index was a power that would result in imaginary numbers. But fq is (in the main code) read from a file, which contains only positive numbers, and I checked that it read correctly, all positive. What else could cause it to return NaN?
Thanks in advance.

ante
Apr 9, 2005

SUNSHINE AND RAINBOWS

DontMockMySmock posted:

code:
#define nfreq 90
float chisquared(float coef, float index, float pixel[nfreq],float fq[nfreq]){
  float sum=0;
  int i=0;
  for(i=0;i<nfreq;i++) {
    sum=sum+(pow(pixel[i]-coef*pow(fq[i],index),2))/(coef*pow(fq[i],index));
    }
  return sum;
}
Given that all of the input variables are always positive and nonzero, how could this code ever return NaN? Because it does, all the time.
The only thing I could figure was if fq was ever negative and index was a power that would result in imaginary numbers. But fq is (in the main code) read from a file, which contains only positive numbers, and I checked that it read correctly, all positive. What else could cause it to return NaN?
Thanks in advance.

Why don't you break it up into multiple lines and use a debugger?

Night Chaos
Jun 8, 2003

Updated version of my parser and scanner, current problem is that the macro to define yylval as a char * isn't working.

As described http://dinosaur.compilertools.net/bison/bison_6.html#SEC44

Line 2 of gram.y sure has that definition right there, but I still get

code:
warning: assignment makes integer from pointer without a cast
Here is my updated tiny code base, thanks for all the help AD. http://filer.case.edu/dsu/vparse.tar


http://rafb.net/p/sdc81r24.html y.tab.h

Night Chaos fucked around with this message at 05:51 on Dec 5, 2008

Smackbilly
Jan 3, 2001
What kind of a name is Pizza Organ! anyway?

DontMockMySmock posted:

code:
#define nfreq 90
float chisquared(float coef, float index, float pixel[nfreq],float fq[nfreq]){
  float sum=0;
  int i=0;
  for(i=0;i<nfreq;i++) {
    sum=sum+(pow(pixel[i]-coef*pow(fq[i],index),2))/(coef*pow(fq[i],index));
    }
  return sum;
}
Given that all of the input variables are always positive and nonzero, how could this code ever return NaN? Because it does, all the time.
The only thing I could figure was if fq was ever negative and index was a power that would result in imaginary numbers. But fq is (in the main code) read from a file, which contains only positive numbers, and I checked that it read correctly, all positive. What else could cause it to return NaN?
Thanks in advance.

Is it possible that one or more of coef, fq[i] and index are very small positive numbers such that the expression coef*pow(fq[i],index) evaluates to a number that is indistinguishable from 0 in single-precision floating point representation? (Anything smaller than 2-149)

If this is the case you may benefit from using doubles instead of floats.

But yeah, either use a debugger or just printf some intermediate parts of the calculation and see where it goes awry for your particular inputs.

Smackbilly fucked around with this message at 07:36 on Dec 5, 2008

tractor fanatic
Sep 9, 2005

Pillbug
is there a way to use sizeof to get the size of a pointer?

nm i'm an idiot :psyduck:

schnarf
Jun 1, 2002
I WIN.

DontMockMySmock posted:

code:
#define nfreq 90
float chisquared(float coef, float index, float pixel[nfreq],float fq[nfreq]){
  float sum=0;
  int i=0;
  for(i=0;i<nfreq;i++) {
    sum=sum+(pow(pixel[i]-coef*pow(fq[i],index),2))/(coef*pow(fq[i],index));
    }
  return sum;
}
Given that all of the input variables are always positive and nonzero, how could this code ever return NaN? Because it does, all the time.
The only thing I could figure was if fq was ever negative and index was a power that would result in imaginary numbers. But fq is (in the main code) read from a file, which contains only positive numbers, and I checked that it read correctly, all positive. What else could cause it to return NaN?
Thanks in advance.
Break it down into a bunch of intermediate calculations, and then use a bunch of asserts that they fall into a valid range (i.e. the denominator is nonzero, the pow() calls don't return NaN, etc.

Smackbilly
Jan 3, 2001
What kind of a name is Pizza Organ! anyway?
nm didn't see the nm

DamageInc
Jan 16, 2004

ultra-inquisitor posted:

It's just for my own edification, I was wondering if there was some cool language feature I didn't know about that might facilitate it. I'm still pretty inexperienced at generic programming.

You could use template specialization if you didn't want to always have to pass in "zero" into the function. You basically would create a template class with a static function "GetZero" (or whatever) which would return zero as defined by that type (either 0, or the identity matrix, or whatever you wanted).

something like this:

code:
// type using the number zero
template < typename T >
class TypeInfoZero
{
public:
	static T GetZero()
	{
		return static_cast < T > ( 0 );
	}
};

// typeinfo using the types default constructor as zero
template < typename T >
class TypeInfoUseDefaultConstructor
{
public:
	static T GetZero()
	{
		return T();
	}
};

// default implementation, using zero
template < typename T >
class TypeInfo : public TypeInfoZero < T >
{
};

// specialization for SomeType where the default constructor should be used for zero
template < >
class TypeInfo < SomeType > : public TypeInfoUseDefaultConstructor < SomeType >
{
};

// specialization for a matrix type using the identity matrix
template < >
class TypeInfo < Matrix >
{
public:
	static T GetZero()
	{
		return Matrix::Identity();
	}
};
Then in your example:
code:
template <typename T>
T sumArray (const vector<T> &arr)
{
	T sum = TypeInfo < T >::GetZero();
	for (size_t i = 0; i < arr.size (); ++i)
		sum += arr[i];

	return sum;
}
You could use a static const variable instead if you wanted.

Jo
Jan 24, 2005

:allears:
Soiled Meat
I'm getting a sigabrt on a delete. I know it's a memory management problem, but I don't see why...

code:
Image * plessyFilter( Image * img, float k = 0.04 ) {
	Image * plessy = new Image( img->getWidth(), img->getHeight() );
	Image * gaussian = runGaussian3x3( img );
	
	// snip!

	delete gaussian;
	return plessy;
}
... the delete fails on the gaussian image. If I use new inside the runGaussian function, it (the blurred image) should NOT be deleted when I return from runGaussian. Why would the data allocated with new disappear on a return?

newsomnuke
Feb 25, 2007

Jo posted:

I'm getting a sigabrt on a delete. I know it's a memory management problem, but I don't see why...

code:
Image * plessyFilter( Image * img, float k = 0.04 ) {
	Image * plessy = new Image( img->getWidth(), img->getHeight() );
	Image * gaussian = runGaussian3x3( img );
	
	// snip!

	delete gaussian;
	return plessy;
}
... the delete fails on the gaussian image. If I use new inside the runGaussian function, it (the blurred image) should NOT be deleted when I return from runGaussian. Why would the data allocated with new disappear on a return?
Is runGaussian3x3 in a different DLL, or are you using new[] to allocate the memory?

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

Jo posted:

I'm getting a sigabrt on a delete. I know it's a memory management problem, but I don't see why...

... the delete fails on the gaussian image. If I use new inside the runGaussian function, it (the blurred image) should NOT be deleted when I return from runGaussian. Why would the data allocated with new disappear on a return?

Why wouldn't you just use a smart pointer there?

newsomnuke
Feb 25, 2007

DamageInc posted:

:words:
I guess there's no way of getting round creating helper classes to implement it after all, but thanks.

Jo
Jan 24, 2005

:allears:
Soiled Meat

ultra-inquisitor posted:

Is runGaussian3x3 in a different DLL, or are you using new[] to allocate the memory?

Right now it's just new[].

Avenging Dentist posted:

Why wouldn't you just use a smart pointer there?

v:shobon:v

Guess I'll have to, but I still don't see why it doesn't work. Perhaps I have a horrid and fundamental misconception about pointers.

code:
int * thingFunc( void ) {
  int * thing = new int[100];
  return thing;
}
The memory set aside using new should not be deleted until I do so manually, yes?

EDIT: I got rid of 'delete gaussian' at the end of the function and the program works. I'm not sure why, exactly, and I'm probably leaking memory; it terminates shortly after returning from the function, so I'm not terribly worried.

EDIT 2: Only for you, Otto Skorzeny. ;-*

A typo in the gaussian function made this:

Jo fucked around with this message at 18:40 on Dec 6, 2008

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip
If you have valgrind you can check whether you're leaking memory pretty easily (as long as your program doesn't have a long run time as-is).


e: hey put that image back up it was :coal:

Jo
Jan 24, 2005

:allears:
Soiled Meat

Otto Skorzeny posted:

If you have valgrind you can check whether you're leaking memory pretty easily (as long as your program doesn't have a long run time as-is).


e: hey put that image back up it was :coal:

Yup, it would seem a leak is present.
==17230== LEAK SUMMARY:
==17230== definitely lost: 2,718,128 bytes in 16 blocks.

Vanadium
Jan 8, 2005

If you allocate memory with new[], you have to deallocate it with delete[].

Jo
Jan 24, 2005

:allears:
Soiled Meat

Vanadium posted:

If you allocate memory with new[], you have to deallocate it with delete[].

Yes, I'm readily aware, but when I call delete[], I get a sigabrt.

EDIT:
Aaah, I see what you're saying. No, it's just a simple Image * gaussian = new Image( blahblah ). The delete still delete, in this case, no?

Jo fucked around with this message at 19:36 on Dec 6, 2008

Vanadium
Jan 8, 2005

It should be, barring some retarded nonstandard semantics.

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.
Do you still get the behavior if you run the snipped version? That is, if you just create it and delete it immediately after?

schnarf
Jun 1, 2002
I WIN.
What does the destructor for Image do? Is it possible that the constructor does something with the pointer to img and then something funky happens in the destructor?

Jo
Jan 24, 2005

:allears:
Soiled Meat

schnarf posted:

What does the destructor for Image do? Is it possible that the constructor does something with the pointer to img and then something funky happens in the destructor?

Image is largely a wrapper for another image library with import/export functionality.

code:
~Image() {
	delete[] redData;
	delete[] greenData;
	delete[] blueData;
	width = 0;
	height = 0;
}
A thousand thank yous to those who responded. I hosed around (rewrote) the gaussian function and things are up and working now. There's still a memory leak, but I don't expect that to be too hard to trace. Again, many many thanks.

Adbot
ADBOT LOVES YOU

FatCow
Apr 22, 2002
I MAP THE FUCK OUT OF PEOPLE
This one had me stumped for a hour or so at work before I got pulled away. When I compile my application everything works fine. When it tries to link I get " undefined reference" to everything in the threadqueue class (Quick wrapper around STL queues to make it threadsafe).

There has to be something so obviously stupid here but I can't see it.

threadqueue.h
code:
#ifndef _THREADQUEUE_H_
#define _THREADQUEUE_H_

#include <pthread.h>

#include <queue>
using namespace std;

template <class T>
class threadqueue {

        private:
                pthread_mutex_t mutex;
                queue<T> data;
        public:
                threadqueue();
                ~threadqueue ();

                void push ( const T& );
                T pop ();
                int size ();
};
#endif
threadqueue.cpp
code:
#include <pthread.h>

#include <queue>
using namespace std;

#include "threadqueue.h"

template <class T> threadqueue<T>::threadqueue () {
        pthread_mutex_init (&mutex, NULL);
}

template <class T> void threadqueue<T>::push( const T& x ) {
        pthread_mutex_lock(&mutex);
        data.push(x);
        pthread_mutex_unlock(&mutex);
}

template <class T> T threadqueue<T>::pop( ) {
        pthread_mutex_lock(&mutex);
        T x;
        x = data.front();
        data.pop();
        pthread_mutex_unlock(&mutex);
        return x;
}

template <class T> int threadqueue<T>::size () {
        return data.size();
}
GCC output
code:
g++ -o threadqueue.o -c -g -O0 -Wall -Ulinux -Dlinux=linux -I/usr/local/ssl/include -pipe -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -I/usr/lib/perl5/5.8.8/i686-linux/CORE threadqueue.cpp
g++ -o acdtool -Wall  threadqueue.o main.o acdtool.o listener.o dialog.o collector.o snmp.o util.o dispatch.o ldr_pcap.o ./libs/libosip2.a ./libs/libosipparser2.a -lpcap -lpthread `net-snmp-config --agent-libs`
acdtool.o: In function `acdtool::main_loop()':
/home/me/acdtool.cpp:86: undefined reference to `threadqueue<acd_message*>::size()'
/home/me/acdtool.cpp:91: undefined reference to `threadqueue<acd_message*>::pop()'
acdtool.o: In function `acdtool::addMessage(acd_message*)':
/home/me/acdtool.cpp:73: undefined reference to `threadqueue<acd_message*>::push(acd_message* const&)'
acdtool.o: In function `~acdtool':
/home/me/acdtool.cpp:68: undefined reference to `threadqueue<acd_message*>::~threadqueue()'
/home/me/acdtool.cpp:68: undefined reference to `threadqueue<acd_message*>::~threadqueue()'
/home/me/acdtool.cpp:68: undefined reference to `threadqueue<acd_message*>::~threadqueue()'
/home/me/acdtool.cpp:68: undefined reference to `threadqueue<acd_message*>::~threadqueue()'
acdtool.o: In function `acdtool':
/home/me/acdtool.cpp:21: undefined reference to `threadqueue<acd_message*>::threadqueue()'
/home/me/acdtool.cpp:36: undefined reference to `threadqueue<acd_message*>::~threadqueue()'
/home/me/acdtool.cpp:21: undefined reference to `threadqueue<acd_message*>::threadqueue()'
/home/me/acdtool.cpp:36: undefined reference to `threadqueue<acd_message*>::~threadqueue()'
collect2: ld returned 1 exit status
make: *** [all] Error 1
$ nm threadqueue.o
$

$ strip threadqueue.o
$ -rw-rw-r-- 1 me me 432 Dec 9 04:26 threadqueue.o

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply