Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. How to print all source code what was running?

How to print all source code what was running?

Scheduled Pinned Locked Moved C / C++ / MFC
tutorialquestion
33 Posts 7 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • U User 13049321

    When breaked at debugging, I can press F10, line by line to view the current execution of the source code. Suppose my program has 1000 lines of code, I don't want to press F10 1000 times to watch all the 1000 line in the order of execution. I wish output whole 1000 lines of code in execution order. surce code like below:

    id fun(int* piVal)
    {
    *piVal = 0;
    }

    main()
    {
    int iTemp = 0;
    fun();
    iTemp = 1;
    }

    I need a text file after running the program. The contents of the file are like below:

    int iTemp = 0;
    *piVal = 0;
    iTemp = 1;

    text file has 3 line, It exact save the three lines of execution.

    S Offline
    S Offline
    Stefan_Lang
    wrote on last edited by
    #5

    A line by line code execution logger doesn't make any sense. The sheer amount of data that would produce for any kind of meaningful program will swiftly exceed any storage capacity that you can throw at it. Not to mention that it would increase computation time by a factor of 100-1000 due to the required IO operations. Much better you learn to use the debugger: simply place a break point at the branch(es) you're interested in and let the debugger run until it hits one of your break points.

    GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

    U 1 Reply Last reply
    0
    • L Lost User

      You can try using "run to cursor" to see if that helps.

      U Offline
      U Offline
      User 13049321
      wrote on last edited by
      #6

      Thanks, I known how to "using run to cursor",but the problem is I need to pressed F10 button hundreds, for execution whole program. I need to view "execution whole program line by line" exacts

      L S 2 Replies Last reply
      0
      • S Stefan_Lang

        A line by line code execution logger doesn't make any sense. The sheer amount of data that would produce for any kind of meaningful program will swiftly exceed any storage capacity that you can throw at it. Not to mention that it would increase computation time by a factor of 100-1000 due to the required IO operations. Much better you learn to use the debugger: simply place a break point at the branch(es) you're interested in and let the debugger run until it hits one of your break points.

        GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

        U Offline
        U Offline
        User 13049321
        wrote on last edited by
        #7

        Thanks,but I sure "

        A line by line code execution logger does make sense for me

        I have very large storage capacity, and I can wait for long time to output.

        S 1 Reply Last reply
        0
        • U User 13049321

          When breaked at debugging, I can press F10, line by line to view the current execution of the source code. Suppose my program has 1000 lines of code, I don't want to press F10 1000 times to watch all the 1000 line in the order of execution. I wish output whole 1000 lines of code in execution order. surce code like below:

          id fun(int* piVal)
          {
          *piVal = 0;
          }

          main()
          {
          int iTemp = 0;
          fun();
          iTemp = 1;
          }

          I need a text file after running the program. The contents of the file are like below:

          int iTemp = 0;
          *piVal = 0;
          iTemp = 1;

          text file has 3 line, It exact save the three lines of execution.

          D Offline
          D Offline
          David Crow
          wrote on last edited by
          #8

          Member 13081369 wrote:

          I don't want to press F10 1000 times to watch all the 1000 line in the order of execution.

          Have you considered setting a breakpoint (that only breaks when a condition is met)?

          "One man's wage rise is another man's price increase." - Harold Wilson

          "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

          "You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles

          K U 2 Replies Last reply
          0
          • U User 13049321

            Thanks, I known how to "using run to cursor",but the problem is I need to pressed F10 button hundreds, for execution whole program. I need to view "execution whole program line by line" exacts

            L Offline
            L Offline
            Lost User
            wrote on last edited by
            #9

            Well good luck, but I don't think you are going to find it.

            1 Reply Last reply
            0
            • D David Crow

              Member 13081369 wrote:

              I don't want to press F10 1000 times to watch all the 1000 line in the order of execution.

              Have you considered setting a breakpoint (that only breaks when a condition is met)?

              "One man's wage rise is another man's price increase." - Harold Wilson

              "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

              "You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles

              K Offline
              K Offline
              k5054
              wrote on last edited by
              #10

              Or a watchpoint that only triggers when a variable changes value? Otherwise, go through and add printf() or cout at "interesting" points. You should be able to wrap those in #ifdef _DEBUG macros so you don't have to pull them out in Release version. A really smart cookie might figure out how to use variadic marcros, #ifdefs, etc so you could do something like

              int main()
              {
              DEBUG_LOG("starting main\n");
              int i = 0, j = 0;
              DEBUG_LOG("i = %d, j = %d\n");
              int n = foo(i,j);
              DEBUG_LOG("foo(%d,%d) returned %d\n", i, j, n);
              DEBUG_LOG("main exits\n");
              }

              If you're using straight C, then vprintf() might help. C++ might need the use of variadic templaytes (C++11 and later - see [c++ - How to make a variadic macro for std::cout? - Stack Overflow](https://stackoverflow.com/questions/29326460/how-to-make-a-variadic-macro-for-stdcout)

              D U 2 Replies Last reply
              0
              • K k5054

                Or a watchpoint that only triggers when a variable changes value? Otherwise, go through and add printf() or cout at "interesting" points. You should be able to wrap those in #ifdef _DEBUG macros so you don't have to pull them out in Release version. A really smart cookie might figure out how to use variadic marcros, #ifdefs, etc so you could do something like

                int main()
                {
                DEBUG_LOG("starting main\n");
                int i = 0, j = 0;
                DEBUG_LOG("i = %d, j = %d\n");
                int n = foo(i,j);
                DEBUG_LOG("foo(%d,%d) returned %d\n", i, j, n);
                DEBUG_LOG("main exits\n");
                }

                If you're using straight C, then vprintf() might help. C++ might need the use of variadic templaytes (C++11 and later - see [c++ - How to make a variadic macro for std::cout? - Stack Overflow](https://stackoverflow.com/questions/29326460/how-to-make-a-variadic-macro-for-stdcout)

                D Offline
                D Offline
                David Crow
                wrote on last edited by
                #11

                Perhaps you meant this reply for the OP?

                "One man's wage rise is another man's price increase." - Harold Wilson

                "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

                "You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles

                1 Reply Last reply
                0
                • D David Crow

                  Member 13081369 wrote:

                  I don't want to press F10 1000 times to watch all the 1000 line in the order of execution.

                  Have you considered setting a breakpoint (that only breaks when a condition is met)?

                  "One man's wage rise is another man's price increase." - Harold Wilson

                  "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

                  "You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles

                  U Offline
                  U Offline
                  User 13049321
                  wrote on last edited by
                  #12

                  The problem is I don't know where are the "condition is met". Whether input's iVal is 1 or 2, first hundreds line code execution are equals. I want to find first diffence between 1 and 2 (iVal), and I sured the diffence appeared after "execution long line codes ago".

                  1 Reply Last reply
                  0
                  • K k5054

                    Or a watchpoint that only triggers when a variable changes value? Otherwise, go through and add printf() or cout at "interesting" points. You should be able to wrap those in #ifdef _DEBUG macros so you don't have to pull them out in Release version. A really smart cookie might figure out how to use variadic marcros, #ifdefs, etc so you could do something like

                    int main()
                    {
                    DEBUG_LOG("starting main\n");
                    int i = 0, j = 0;
                    DEBUG_LOG("i = %d, j = %d\n");
                    int n = foo(i,j);
                    DEBUG_LOG("foo(%d,%d) returned %d\n", i, j, n);
                    DEBUG_LOG("main exits\n");
                    }

                    If you're using straight C, then vprintf() might help. C++ might need the use of variadic templaytes (C++11 and later - see [c++ - How to make a variadic macro for std::cout? - Stack Overflow](https://stackoverflow.com/questions/29326460/how-to-make-a-variadic-macro-for-stdcout)

                    U Offline
                    U Offline
                    User 13049321
                    wrote on last edited by
                    #13

                    Thanks, but I want to find a way that don't add any code like DEBUG_LOG(), to print source code. because the source code too many. I wouldn't be do this otherwise.

                    S 1 Reply Last reply
                    0
                    • U User 13049321

                      When breaked at debugging, I can press F10, line by line to view the current execution of the source code. Suppose my program has 1000 lines of code, I don't want to press F10 1000 times to watch all the 1000 line in the order of execution. I wish output whole 1000 lines of code in execution order. surce code like below:

                      id fun(int* piVal)
                      {
                      *piVal = 0;
                      }

                      main()
                      {
                      int iTemp = 0;
                      fun();
                      iTemp = 1;
                      }

                      I need a text file after running the program. The contents of the file are like below:

                      int iTemp = 0;
                      *piVal = 0;
                      iTemp = 1;

                      text file has 3 line, It exact save the three lines of execution.

                      L Offline
                      L Offline
                      Lost User
                      wrote on last edited by
                      #14

                      Hi, You could use the [Debug Interface Access SDK](https://docs.microsoft.com/en-us/visualstudio/debugger/debug-interface-access/debug-interface-access-sdk?view=vs-2017) to get the exact line of 'source code' associated with any instruction offset in the executable. This is how WinDbg and Visual Studio knows where the line of source code is located. Using your sample:

                      main()
                      {
                      int iTemp = 0; __asm int 3;
                      fun(); __asm int 3;
                      iTemp = 1; __asm int 3;
                      }

                      Then add an exception hander for STATUS_BREAKPOINT (0x80000003) and call into DIA and pass the exception offset to get the source line. It's actually quite simple. However if you are looking to perform instrumentation at the instruction level then have a look at [DynamoRIO](https://www.dynamorio.org/) and specifically the [instrace_x86 sample](https://github.com/DynamoRIO/dynamorio/blob/master/api/samples/instrace\_x86.c). Best Wishes, -David Delaune

                      U S 2 Replies Last reply
                      0
                      • U User 13049321

                        If the code like below:

                        if(iVal < 10)
                        {
                        FunA();
                        }
                        else
                        {
                        FunB();
                        }

                        When first run, iVal=1. So the first.txt Should be:

                        if(iVal < 10)
                        FunA();

                        And second run, iVal=20. The second.txt Should be:

                        if(iVal < 10)
                        FunB();

                        I could compared two file(first.txt and second.txt) to find code execution difference.

                        I need it, because my codes very very larged. when iVal differeced every times, the differece appeard at after hundreds lines between first.txt and second.txt.

                        H Offline
                        H Offline
                        HS_C_Student
                        wrote on last edited by
                        #15

                        It's hard to understand your question. I think there are many better ways of solving the problem which might include restructuring the program, especially to make that section into smaller modules or to create your own debugging interface and pass parameters through it so you have a functional means of tracking program states. If you could tighten up input validation and narrow the scope of acceptable input it may help detect bugs. The way you want to do it printing code is not even remotely a standard functionality or common practice so it is a very oversized foot you are trying to shoehorn into a small shoe and the result will likely be as comfortable. If you want to pursue it anyway it's hard to imagine without knowing your code. You could set up a custom table of watch variables and or expressions and use the stringizing operator in a macro, similar to an assert() style. #define record_str (a) (fprintf(debug, "%s : %s", #a, a)) #define record_int(a) (fprintf(debug, "%s : %s", #a, itoa(a))) Combine it with __LINE__ and or FILE or TIME C/C++ line number - Stack Overflow[^] Hope this helps

                        U 1 Reply Last reply
                        0
                        • U User 13049321

                          When breaked at debugging, I can press F10, line by line to view the current execution of the source code. Suppose my program has 1000 lines of code, I don't want to press F10 1000 times to watch all the 1000 line in the order of execution. I wish output whole 1000 lines of code in execution order. surce code like below:

                          id fun(int* piVal)
                          {
                          *piVal = 0;
                          }

                          main()
                          {
                          int iTemp = 0;
                          fun();
                          iTemp = 1;
                          }

                          I need a text file after running the program. The contents of the file are like below:

                          int iTemp = 0;
                          *piVal = 0;
                          iTemp = 1;

                          text file has 3 line, It exact save the three lines of execution.

                          V Offline
                          V Offline
                          Victor Nijegorodov
                          wrote on last edited by
                          #16

                          Suppose you have a block in your code like:

                          static int someNumber = 100000;
                          ...
                          for(int i = 0; i < someNumber; ++i)
                          {
                          int a = 0;
                          ...
                          double b = (double )a++;
                          ...
                          // some more (ca. 20) lines
                          }

                          Now tell us how are you going to analyze those 20 * 100000 = 2 million lines of the executed code? :confused: :sigh:

                          U 1 Reply Last reply
                          0
                          • H HS_C_Student

                            It's hard to understand your question. I think there are many better ways of solving the problem which might include restructuring the program, especially to make that section into smaller modules or to create your own debugging interface and pass parameters through it so you have a functional means of tracking program states. If you could tighten up input validation and narrow the scope of acceptable input it may help detect bugs. The way you want to do it printing code is not even remotely a standard functionality or common practice so it is a very oversized foot you are trying to shoehorn into a small shoe and the result will likely be as comfortable. If you want to pursue it anyway it's hard to imagine without knowing your code. You could set up a custom table of watch variables and or expressions and use the stringizing operator in a macro, similar to an assert() style. #define record_str (a) (fprintf(debug, "%s : %s", #a, a)) #define record_int(a) (fprintf(debug, "%s : %s", #a, itoa(a))) Combine it with __LINE__ and or FILE or TIME C/C++ line number - Stack Overflow[^] Hope this helps

                            U Offline
                            U Offline
                            User 13049321
                            wrote on last edited by
                            #17

                            Thank you

                            1 Reply Last reply
                            0
                            • V Victor Nijegorodov

                              Suppose you have a block in your code like:

                              static int someNumber = 100000;
                              ...
                              for(int i = 0; i < someNumber; ++i)
                              {
                              int a = 0;
                              ...
                              double b = (double )a++;
                              ...
                              // some more (ca. 20) lines
                              }

                              Now tell us how are you going to analyze those 20 * 100000 = 2 million lines of the executed code? :confused: :sigh:

                              U Offline
                              U Offline
                              User 13049321
                              wrote on last edited by
                              #18

                              struct stNode
                              {
                              union sss_ {
                              struct sns_ {
                              int iType;
                              float fType;
                              } s_name;
                              } s_ss;

                              stNode\* pNext;
                              

                              };

                              int FunA(stNode* pNode)
                              {
                              if (pNode->pNext->pNext->pNext->s_ss.s_name.iType>10)
                              {
                              ...
                              pNode->pNext->s_ss.s_name.fType = 4.0f;
                              pNode->pNext = pNode->pNext + pNode->iType;

                              		return pNode->pNext->pNext->s\_ss.s\_name.iType;
                              }
                              pNode->pNext = pNode->pNext + pNode->iType;
                              pNode->pNext->s\_ss.s\_name.fType = 7.0f;
                              ...
                              return pNode->s\_ss.s\_name.iType;
                              

                              }

                              main()
                              {

                              int iVal = 2;

                              	for(int i = 0; i < 100; ++i)
                              	{		
                              		iVal++;
                              
                              		stNode stMyNode;
                              
                              		if (iVal<100)
                              		{
                              			iVal = FunA(&stMyNode+iVal);
                              		}
                              		else
                              		{
                              			iVal = FunB(&stMyNode+iVal);
                              		}
                              	}
                              

                              }

                              With difference iVal initialization. the difference of execution occured at hundreds lines run after begin of main(). And, the actual code of mine, are complex than above are. Very very complex, run one FunA(),need a lot of times. (many lines code)

                              V 1 Reply Last reply
                              0
                              • L Lost User

                                Hi, You could use the [Debug Interface Access SDK](https://docs.microsoft.com/en-us/visualstudio/debugger/debug-interface-access/debug-interface-access-sdk?view=vs-2017) to get the exact line of 'source code' associated with any instruction offset in the executable. This is how WinDbg and Visual Studio knows where the line of source code is located. Using your sample:

                                main()
                                {
                                int iTemp = 0; __asm int 3;
                                fun(); __asm int 3;
                                iTemp = 1; __asm int 3;
                                }

                                Then add an exception hander for STATUS_BREAKPOINT (0x80000003) and call into DIA and pass the exception offset to get the source line. It's actually quite simple. However if you are looking to perform instrumentation at the instruction level then have a look at [DynamoRIO](https://www.dynamorio.org/) and specifically the [instrace_x86 sample](https://github.com/DynamoRIO/dynamorio/blob/master/api/samples/instrace\_x86.c). Best Wishes, -David Delaune

                                U Offline
                                U Offline
                                User 13049321
                                wrote on last edited by
                                #19

                                Using your method, I need add “__asm int 3;” for every line of code?

                                L 1 Reply Last reply
                                0
                                • U User 13049321

                                  Using your method, I need add “__asm int 3;” for every line of code?

                                  L Offline
                                  L Offline
                                  Lost User
                                  wrote on last edited by
                                  #20

                                  Member 13081369 wrote:

                                  Using your method, I need add “__asm int 3;” for every line of code?

                                  No, You could set the hardware breakpoints at DR0-DR7 and automate every single-step through your entire program printing out each line of source code as it is executed by querying the [PDB file](https://blogs.msdn.microsoft.com/vcblog/2016/02/08/whats-inside-a-pdb-file/) associated with the executable via [DIA](https://docs.microsoft.com/en-us/visualstudio/debugger/debug-interface-access/debug-interface-access-sdk?view=vs-2017). What you are asking is absolutely possible but it's a lot of work. Are you sure that you need to do this? Best Wishes, -David Delaune

                                  U 1 Reply Last reply
                                  0
                                  • L Lost User

                                    Member 13081369 wrote:

                                    Using your method, I need add “__asm int 3;” for every line of code?

                                    No, You could set the hardware breakpoints at DR0-DR7 and automate every single-step through your entire program printing out each line of source code as it is executed by querying the [PDB file](https://blogs.msdn.microsoft.com/vcblog/2016/02/08/whats-inside-a-pdb-file/) associated with the executable via [DIA](https://docs.microsoft.com/en-us/visualstudio/debugger/debug-interface-access/debug-interface-access-sdk?view=vs-2017). What you are asking is absolutely possible but it's a lot of work. Are you sure that you need to do this? Best Wishes, -David Delaune

                                    U Offline
                                    U Offline
                                    User 13049321
                                    wrote on last edited by
                                    #21

                                    First, I sure. I run DIA SDK\Samples\DIA2Dump\Dia2Dump.exe myProgram.pdb I can view values and functions list when Dia2Dump.exe is run. But, How to "set the hardware breakpoints at DR0-DR7 and automate every single-step through your entire program"? Is modify dia2dump.cpp -> main(), start my program by dia2dump.exe? and WaitForDebugEvent(&dbgEvent, INFINITE); in dia2dump.exe? Can you give me a sample?

                                    L 1 Reply Last reply
                                    0
                                    • U User 13049321

                                      struct stNode
                                      {
                                      union sss_ {
                                      struct sns_ {
                                      int iType;
                                      float fType;
                                      } s_name;
                                      } s_ss;

                                      stNode\* pNext;
                                      

                                      };

                                      int FunA(stNode* pNode)
                                      {
                                      if (pNode->pNext->pNext->pNext->s_ss.s_name.iType>10)
                                      {
                                      ...
                                      pNode->pNext->s_ss.s_name.fType = 4.0f;
                                      pNode->pNext = pNode->pNext + pNode->iType;

                                      		return pNode->pNext->pNext->s\_ss.s\_name.iType;
                                      }
                                      pNode->pNext = pNode->pNext + pNode->iType;
                                      pNode->pNext->s\_ss.s\_name.fType = 7.0f;
                                      ...
                                      return pNode->s\_ss.s\_name.iType;
                                      

                                      }

                                      main()
                                      {

                                      int iVal = 2;

                                      	for(int i = 0; i < 100; ++i)
                                      	{		
                                      		iVal++;
                                      
                                      		stNode stMyNode;
                                      
                                      		if (iVal<100)
                                      		{
                                      			iVal = FunA(&stMyNode+iVal);
                                      		}
                                      		else
                                      		{
                                      			iVal = FunB(&stMyNode+iVal);
                                      		}
                                      	}
                                      

                                      }

                                      With difference iVal initialization. the difference of execution occured at hundreds lines run after begin of main(). And, the actual code of mine, are complex than above are. Very very complex, run one FunA(),need a lot of times. (many lines code)

                                      V Offline
                                      V Offline
                                      Victor Nijegorodov
                                      wrote on last edited by
                                      #22

                                      Member 13081369 wrote:

                                      ... the actual code of mine, are complex than above are. Very very complex, run one FunA(),need a lot of times. (many lines code)

                                      And how will you analyze such a "many lines code" in your "line output"? How much time would you need to just to look in this output?

                                      U 1 Reply Last reply
                                      0
                                      • U User 13049321

                                        Thanks,but I sure "

                                        A line by line code execution logger does make sense for me

                                        I have very large storage capacity, and I can wait for long time to output.

                                        S Offline
                                        S Offline
                                        Stefan_Lang
                                        wrote on last edited by
                                        #23

                                        No it doesn't. You don't understand what you're asking for. Even if it would kind of work out for the very simple program you are looking at right now, it won't help you beyond that: the next time you're trying to understand some code, it won't be good enough, and you will eventually realize that you wasted a lot of time with a tool that, in the end, doesn't really help. Please take the advice from people who have spent decades on programming and using tools. The debugger is the second tool I learned to use after the editor, and it is still the most helpful tool I use today. Without it, large scale applications wouldn't be possible, and smaller ones would cost orders of magnitude more money and time to develop. With a debugger you can do the inspection you're asking for at runtime, and a lot more. You won't need to write one yourself, nyou won't have to wait for it's output to be written, and you won't waste ludicrous amouunts of storage space. It's better in any way you can think of.

                                        GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

                                        1 Reply Last reply
                                        0
                                        • U User 13049321

                                          Thanks, but I want to find a way that don't add any code like DEBUG_LOG(), to print source code. because the source code too many. I wouldn't be do this otherwise.

                                          S Offline
                                          S Offline
                                          Stefan_Lang
                                          wrote on last edited by
                                          #24

                                          This response shows that you have really no understanding of what a debugger does, and how to use it. A debugger does not require you to add anything to your code at all. There's no need for a debugger to print code, nor to add any code to your program. You really should read this up before continuing to refuse the only sensible advice any experienced programmer can offer you on this problem: Debugger - Wikipedia[^]

                                          GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

                                          1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • World
                                          • Users
                                          • Groups